First published at: github.com/USTB-musion…

Writing in the front

Webpack is arguably the most popular packaging library of the moment. When WebPack works with an application, it recursively builds a dependency graph that contains every module the application needs, and then packages all those modules into one or more bundles. This article introduces a very important part of WebPack – performance tuning. The code for this article is here: github.com/USTB-musion…

This paper will summarize from the following parts:

  1. noParse
  2. ignorePlugin
  3. dllPlugin
  4. happypack
  5. Tree-Shaking
  6. Pull out the common code
  7. Lazy loading
  8. Hot update

noParse

  • The noParse configuration item allows Webpack to ignore recursive parsing and processing of portions of files that are not modularized, which has the benefit of improving build performance. The reason for this is that some libraries such as jQuery and ChartJS are huge and do not adopt modular standards, making it time-consuming and pointless for Webpack to parse these files.

Enable noParse:

  module: {
    // Do not parse jquery dependencies
    noParse: /jquery/
  },
Copy the code

ignorePlugin

  • Moment 2.18 will pack all localized content with core features). IgnorePlugin can be used to ignore localized content while packaging. In experiments, the size of 📦 was reduced from 1.2m to 800K after using IgnorePlugin

IgnorePlugin Enable method:

/ / usage:
new webpack.IgnorePlugin(requestRegExp, [contextRegExp]);

//eg.
plugins: [new webpack.IgnorePlugin(/\.\/local/./moment/)];
Copy the code

DllPlugin

  • DllPlugin was created based on the idea of Windows Dynamic link Libraries (DLLS). The plugin packages the third-party library into a separate file, which is a pure dependency library. The dependency library is not repackaged along with your business code, only when the dependency itself changes version.

Using the DllPlugin to process files takes two steps:

  • DLL – specific configuration file based on packaging DLL libraries
let path = require("path");
let webpack = require("webpack");

module.exports = {
  mode: "development".entry: {
    react: ["react"."react-dom"]},output: {
    filename: "_dll_[name].js".// The generated file name
    path: path.resolve(__dirname, "dist"),
    library: "_dll_[name]"
  },
  plugins: [
    // Name is equal to the name in the library
    new webpack.DllPlugin({
      name: "_dll_[name]".path: path.resolve(__dirname, "dist"."manifest.json")]}});Copy the code
  • Package business code based on webpack.config.js file
let path = require("path");
let HtmlWebpackPlugin = require("html-webpack-plugin");
let webpack = require("webpack");

module.exports = {
  mode: "development"./ / entrance
  entry: {
    home: "./src/index.js"
  },
  devServer: {
    port: 3000.open: true.contentBase: "./dist"
  },
  module: {
    // Do not parse jquery dependencies
    noParse: /jquery/,
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader"."css-loader"] {},test: /\.js$/,
        exclude: /node_modules/,
        include: path.resolve("src"),
        use: {
          loader: "babel-loader".options: {
            presets: ["@babel/preset-env"."@babel/preset-react"]}}}]},output: {
    // name -> home a
    filename: "[name].js".path: path.resolve(__dirname, "dist")},plugins: [
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, "dist"."manifest.json")}),new webpack.IgnorePlugin(/\.\/local/./moment/),
    new HtmlWebpackPlugin({
      template: "./src/index.html".filename: "index.html"
    }),
    new webpack.DefinePlugin({
      DEV: JSON.stringify("production")]}});Copy the code

Happypack – Changes loader from a single process to multiple processes

  • As you all know, WebPack is single-threaded, so even if there are multiple tasks at the moment, you can only queue up one after another for processing. This is a disadvantage of Webpack. Fortunately, our CPU is multi-core, Happypack will fully release the advantages of multi-core concurrency, helping us to split tasks into multiple sub-processes for concurrent execution, greatly improving packaging efficiency.

Happypack uses the following methods:

Happypack: Happypack: happypack: Happypack

let path = require("path");
let HtmlWebpackPlugin = require("html-webpack-plugin");
let webpack = require("webpack");
// The happypack module can implement multithreading 📦
let Happypack = require("happypack");

module.exports = {
  mode: "development"./ / entrance
  entry: {
    home: "./src/index.js"
  },
  devServer: {
    port: 3000.open: true.contentBase: "./dist"
  },
  module: {
    // Do not parse jquery dependencies
    noParse: /jquery/,
    rules: [
      {
        test: /\.css$/,
        use: "Happypack/loader? id=css"
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        include: path.resolve("src"),
        use: "Happypack/loader? id=js"}},output: {
    // name -> home a
    filename: "[name].js".path: path.resolve(__dirname, "dist")},plugins: [
    new Happypack({
      id: "css".use: ["style-loader"."css-loader"]}),new Happypack({
      id: "js".use: [{loader: "babel-loader".options: {
            presets: ["@babel/preset-env"."@babel/preset-react"]}}]}),new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, "dist"."manifest.json")}),new webpack.IgnorePlugin(/\.\/local/./moment/),
    new HtmlWebpackPlugin({
      template: "./src/index.html".filename: "index.html"
    }),
    new webpack.DefinePlugin({
      DEV: JSON.stringify("production")]}});Copy the code

Tree-Shaking

  • With the import/export syntax, tree-shaking can learn during compilation which modules are not actually being used, and this code is removed at the end of packaging. Suitable for working with module-level code, use es6’s import/export syntax whenever possible.

Pull out the common code

Benefits of pulling common code out:

  • Reduce network transmission traffic, reduce server cost;
  • While the first time a user opens the site, the speed of subsequent visits to other pages will be greatly improved.

Enable the extraction code:

  // commonChunkPlugins prior to webPack 4.x
  optimization: {
    // Split code blocks
    splitChunks: {
      / / cache group
      cacheGroups: {
        // Public module
        common: {
          chunks: "initial".minSize: 0.// Minimum number of public modules
          minChunks: 2
        },
        vendor: {
          priority: 1.// Pull it out
          test: /node_modules/,
          chunks: "initial".minSize: 0.minChunks: 2}}}}Copy the code

According to the need to load

The idea of loading on demand

  • Do not load all the contents of the file at once, only load the parts needed at the moment (will be split in advance)
  • When more content is needed, the content used is loaded in real time

Load on demand via ES6’s import. After splitting the code with import(), your browser needs to support the Promise API for the code to work, because import() returns a Promise, which relies on promises. For browsers that don’t natively support Promises, you can inject Promise Polyfill.

let button = document.createElement("button");

button.innerHTML = "musion";

// React lazy loading works the same way
button.addEventListener("click".function() {
  // Es6 draft syntax, jSONP implements dynamic file loading
  import("./source.js").then(data= > {
    console.log(data.default);
  });
  console.log("click");
});

document.body.appendChild(button);
Copy the code

Hot update

Hmr-hot Module Replacement is one of the most useful features webPack provides. It allows you to replace, add, and remove modules at runtime without having to completely refresh and reload the entire page. The idea is as follows:

  • Preserve the state of the application that was lost when the page was fully reloaded
  • Only update what has changed to save development time
  • Adjusting styles is much faster, almost the same as changing styles in the browser debugger

Enable the HRM

  1. The Webpack library was introduced
  2. Using the new webpack. HotModuleReplacementPlugin ()
  3. Set the hot field in the devServer option to true
let path = require("path");
let HtmlWebpackPlugin = require("html-webpack-plugin");
let webpack = require("webpack");

module.exports = {
  mode: "production"./ / entrance
  entry: {
    index: "./src/index.js".other: "./src/other.js"
  },
  devServer: {
    // Enable hot updates
    hot: true.port: 3000.open: true.contentBase: "./dist"
  },
  module: {
    rules: [{test: /\.js$/,
        exclude: /node_modules/,
        include: path.resolve("src"),
        use: {
          loader: "babel-loader".options: {
            presets: ["@babel/preset-env"."@babel/preset-react"].plugins: ["@babel/plugin-syntax-dynamic-import"]}}}]},output: {
    // name -> home a
    filename: "[name].js".path: path.resolve(__dirname, "dist")},plugins: [
    new webpack.NamedModulesPlugin(), // Prints the updated module path
    new webpack.HotModuleReplacementPlugin() // Hot update plugin]};Copy the code

Refer to the article

How does Webpack implement hot updates?

Front-end performance optimization principles and practices

You can pay attention to my public account “Muchen classmates”, goose factory code farmers, usually record some trivial bits, technology, life, perception, grow together.