Package size optimization after webpack 3. X upgrade to 4. X

Time:2021-9-19

preface

LastWe talked about the problems, causes and solutions encountered during the upgrade of webpack3. X to 4. X. let’s talk about them todaywebpack 4.xPackaging Optimization for.

Packaged Analytics

Before optimization, we need to know the packaging of the project,npm run buildafterwebpackThe packaging information will be printed to the terminal, such as:

Package size optimization after webpack 3. X upgrade to 4. X

We can see that there are several large files, but we don’t know which modules are included, which modules are suitable for separate extraction, and which modules are not suitable for extraction. At this time, we need to use the packaging analysis tool.

The following is taken fromWebpack document

Bundle analysis – Packaging Analysis

Once you start splitting code, it’s useful to analyze the output to see where the module ends.official analyze toolIs a good starting point. There are other community supported options:

  • webpack-chart: interactive pie chart for webpack statistics
  • webpack-visualizer: visualize and analyze your package to see which modules are taking up space and which may be duplicated.
  • webpack-bundle-analyzer: a plug-in and cli utility that represents the contents of a package as a convenient interactive scalable tree.
  • webpack bundle optimize helper: This tool will analyze your bundle and provide you with practical suggestions for improvement to reduce the bundle size.
  • bundle-stats: generate bundle report (bundle size, asset, module) and compare the results between different versions.

What we use here iswebpack-bundle-analyzer, interactive and scalable tree diagram, which is convenient for us to have a more intuitive understanding of packaging.

Install plug-ins

npm i -D webpack-bundle-analyzer

Introducing plug-ins

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;

module.exports = {
  plugins: [new BundleAnalyzerPlugin()],
};

Then we’ll try to build the following and see what happens

npm run build

The plug-in automatically opens the link in the browser:http://127.0.0.1: 8888 /, showing the packaging of the current project in an interactive and scalable tree diagram, you can clearly see the modules contained in each file, and the targeted processing:

Package size optimization after webpack 3. X upgrade to 4. X

Code splitting

Analysis above? The following points that can be optimized are summarized in the tree diagram of:

  • Extract the common dependencies of the two entries, such as element UI, Vue, lodash, etc
  • Extract the dependencies used by only one component, such as swiper
  • Other dependencies, as a separate part

takeoptimization.splitChunksProperty, and thencacheGroupsThe configuration in is as follows:

webpack.prod.js

// ..
const webpackConfig = merge(baseWebpackConfig, {
  // ..
  optimization: {
    splitChunks: {
-     chunks: "async",
-     minSize: 30000,
-     maxSize: 0,
-     minChunks: 1,
-     maxAsyncRequests: 5,
-     maxInitialRequests: 3,
-     automaticNameDelimiter: "~",
-     automaticNameMaxLength: 30,
-     name: true,
      cacheGroups: {
+       common: {
+         test: /[\\/]node_modules[\\/]/,
+         name: 'vendors-common',
+         minSize: 0,
+Minchunks: 2, // referenced by at least 2 chunks
+         chunks: 'initial',
+Priority: 1 // priority is 0 by default and can be negative
+       },
+       other: {
+         test: /[\\/]node_modules[\\/]/,
+         name: 'vendors-other',
+         chunks: 'initial',
+         priority: -10
+       },
-       defaultVendors: {
-         test: /[\\/]node_modules[\\/]/,
-         priority: -10
-       },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
  // ..
});

// ..
module.exports = webpackConfig;

Let’s build again and see

npm run build

Package size optimization after webpack 3. X upgrade to 4. X
Package size optimization after webpack 3. X upgrade to 4. X

You can see that several containingnode_modulesLarge file:

  • Vendors common. * * * *. JS (dependencies common to two entries, referenced more than twice)
  • Vendors other. * * * *. JS (other dependencies, used in a single entry, used globally)
  • 5.***.js(swiper, dependencies introduced in a single component,webpack(automatically extracted)
  • The dependency files used in other projects and automatically split are small, which is not reflected in the figure above

Compare the file sizes of the two entries before and after code splitting:

  • Before splitting:_ app(2.5MB) qi(1.04MB)_
  • After splitting:_ app(1.88MB)qi(1.04MB)_

There is no change in entry 2, and the loaded file size of entry 1 is reduced0.62MB, shrink nearly25%Of course, this is not going ongzipIn the case of compressionnginxEnabled on servergzipThe compressed overall size will be smaller, so it will not be expanded here

If you want to extract some dependencies separately, you can see the official oneexample, if your project is less dependent, you can manually split your project dependencies into multiple files according to your favorite combination.

Cache (CACHE)

When accessing a web page, the requested file will be stored in the browser’s cache. If it is satisfied the next timeHTTP caching mechanism, the browser can read files from the cache without reading from the server or even initiating requests, which can significantly improve the loading speed and reduce traffic consumption.

But what if the project is rebuilt and the cache in the user’s browser has not expired, and you want to quickly update and continue to keep some of the cache?

Package size optimization after webpack 3. X upgrade to 4. X

For more details,HTTP cache – discard and update cached responses

In this regardwebpackThe following points need to be optimized for packaging:

  • Control the name of the output file – contenthash
  • Extract runtime code – runtimechunk
  • Specify module identifier – moduleid

webpack.prod.js

// ..
const webpackConfig = merge(baseWebpackConfig, {
  // ..
  output: {
    // ..
-   filename: utils.assetsPath('js/[name].[chunkhash].js')
+// the hash generated according to the file content. When the file content changes, the hash also changes
+   filename: utils.assetsPath('js/[name].[contenthash].js')
  },
  optimization: {
+// the runtime block contains the reference relationship between modules. Extract it as a separate file. When the reference relationship changes, irrelevant file contents will not change
+   runtimeChunk: 'single',
+// because hashed is used, when dependencies are added or reduced locally, the IDs of other modules will not be affected (by default, the ID value is incremented according to the resolution order)
+   moduleIds: 'hashed'
    // ...
  }
});

// ..
module.exports = webpackConfig;

For more details,Webpack document – cache (CACHE)

summary

In the process of code splitting, an attempt has been made to separate the specified dependencies based on the existing configuration (e.gElement-UI, because it is not often changed and the file is large), but it will destroy the existing split. After many attempts, it is fruitless. The closest time is this. Entry 1 will include it in the file, but entry 2 will not. The current project has two entries:

Package size optimization after webpack 3. X upgrade to 4. X

The following configuration is adopted:

// ..
const webpackConfig = merge(baseWebpackConfig, {
  // ..
  optimization: {
    splitChunks: {
      cacheGroups: {
        common: {
-         test: /[\\/]node_modules[\\/]/,
+         test: /[\\/]node_modules[\\/]((?!(element-ui)).)+[\\/]/,
          name: 'vendors-common',
          minSize: 0,
          Minchunks: 2, // referenced by at least 2 chunks
          chunks: 'initial',
          Priority: 1 // priority is 0 by default and can be negative
        },
        other: {
-         test: /[\\/]node_modules[\\/]/,
+         test: /[\\/]node_modules[\\/]((?!(element-ui)).)+[\\/]/,
          name: 'vendors-other',
          chunks: 'initial',
          priority: -10
        },
+       'element-ui': {
+         test: /[\\/]node_modules[\\/](element-ui)[\\/]/,
+         name: 'vendor-element-ui',
+         chunks: 'initial',
+         priority: -15
+       },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
  // ..
});

// ..
module.exports = webpackConfig;

The subsequent processing scheme will be updated after it is available. Here, the packaging size optimization will come to an end. The next article will talk about how to optimize the packaging speed.