preface

The size of the product webPack builds directly affects the performance of our online pages, so I’ve summarized some optimization points.

Optimization for webPack build speed can be found at juejin.cn/post/698032…

Tree-shaking

Tree-shaking is a way to remove dead code (unused code) based on ES Modules. It statically analyzes the import and export relationships of modules at runtime, and determines which fields are not used and then removes them. Webpack automatically turns tree-shaking on in the Production environment.

Tree-shaking startup conditions

  • Write code using ESM specifications
  • configurationoptimization.usedExports 为 trueTo enable the tag function
    • Set mode = production

    • Optimization. Minimize = true

    • Provides an array of optimization.minimizer

Theoretical basis

For example, the commonJS specification is loaded at run time. If the analysis file is imported or exported, there is great uncertainty. However, ES Module is introduced at compile time, and the dependency between its files can be determined, so the compiler only needs to conduct static analysis of the code to determine whether it is used by other modules.

The principle of

1. Collect modules. First, tree-shaking collects information exported by modules. 2. Module marking stage. Then go back to the collected modules to mark the modules that were not exported. 3. Code generation and dead code deletion. Webpack will generate code based on the usage of exported values, and Terser and UglifyJS plug-ins will delete the exported but unused code.

Suggestions for preventing tree-shaking from failing

  • A package that supports ES Module is recommended

The LoDash library, for example, can use the LODash-es package that supports ESM.

  • use#pureAnnotate pure function calls

Annotate the function with /*#__PURE__*/ to tell WebPack that the function call has no contextual side effects.

  • Optimize the granularity of file export
function a() {
   console.log(234)}function b() {
   console.log(123)}export default {
    a, b
}
Copy the code

If only one of these two functions is referenced in other files, we can import them as needed, but export default will export the other one.

export {
    a, b
}
Copy the code
  • Disallow the Babel translation module to import and export statements

Babel provides some features that make Tree Shaking invalid. For example, Babel can translate import/export style ESM statements into CommonJS style modular statements. However, this feature prevents Webpack from doing static analysis of translated module imports and exports, which makes It impossible for Webpack to do tree shaking.

Code Splitting

Why is code subcontracting necessary?

  • Large resources and long loading time: During the first screen rendering, many JS files may not be used, but they are also loaded during initialization, resulting in large resources and long rendering time on the first screen.
  • Hard to hit cache resources: When multiple files are packaged together, even if only one file changes something, the entire resource bundle will fail to hit the cache and be reloaded.

Optimization approach

  • Multi-route pages are subcontracted according to routes to reduce the rendering time of the first screen
  • Subcontracting third-party libraries: When several third-party libraries are used on multiple pages, packaging them into code can cause them to reload, so we can remove them from the business code.
  • Limit the size of the subcontract: We can control the size of the maxSize of the subcontract, maximize hit caching, and combine it with HTTP2 multiplexing features for performance optimization.

Static resource compression

JS code compression

TerserWebpackPlugin: This plug-in uses Terser to compress JavaScript.

// webpack.config.js
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
  },
};
Copy the code

CSS extraction and compression

Mini-css-extract-plugin: This plug-in extracts CSS into a separate file. It creates a CSS file for each JS file that contains CSS. It supports loading CSS and SourceMap on demand.

Css-minimizer-webpack-plugin: This plugin can compress CSS files.

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [new MiniCssExtractPlugin()],
};
Copy the code

Image compression

Image-webpack-loader: This plug-in can compress and degrade images.

rules: [{
  test: /.(gif|png|jpe? g|svg)$/i,
  use: [
    'file-loader',
    {
      loader: 'image-webpack-loader'.options: {
        mozjpeg: {
          progressive: true,},// optipng.enabled: false will disable optipng
        optipng: {
          enabled: false,},pngquant: {
          quality: [0.65.0.90].speed: 4
        },
        gifsicle: {
          interlaced: false,},// the webp option will enable WEBP
        webp: {
          quality: 75}},},],}]Copy the code

HTML compression

const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { plugins: [ new HtmlWebpackPlugin({ // ... minify: { removeComments: CollapseWhitespace: true, // Delete white space and newline characters minifyCSS: true // Collapse inline CSS}})]}Copy the code

Reduce packaging of unnecessary files for third-party packages

For example, moment.js will automatically import all the language packages each time it is packaged. We can use IgnorePlugin to ignore unwanted language package folders.

new webpack.IgnorePlugin(/^./locale$/, /moment$/)
Copy the code