directory

  • Webpack5 new features
  • Summary of problems upgrading to webpack5
  • Start optimizing terms
  • To optimize
    • Use the new cache attributes to optimize the cache
    • Resolve partial optimization
    • Module partial optimization
    • Optimization of
    • The plugin part
    • Multithreaded packaging
    • Other optimizations
  • The final result

1. New webPack5 features

  • Increased persistent storage capability to improve build performance (core)
  • Improve algorithmic capabilities to improve long-term caching (reduce cache failure rates for production resources)
  • Improved Tree Shaking reduces product size and code generation logic
  • Improve web platform compatibility
  • Cleaned up some weird states in the internal architecture that were left over when Webpack4 introduced some new features without a major update
  • Long term stability in Webpack5 releases by introducing some significant changes to prepare for future features

2. Upgrade to WebPack5

Fault 1: The format of the env environment object is changed

Cause: In Webpack4, –env.xx XXX is used to pass environment variables to the webpack.config file. In Webpack5, the following error is reported

–env. Xx XXX –env xx= XXX

Error 2: Webpack-dev-server Cannot find module ‘webpack-cli/bin/config-yargs

Solution: Change webpack-dev-server to Webpack serve, or change webpack-CLI version to 3.x

Question 3: Using babel-loader? CacheDirectory error

Solution:

  1. Use the cache added in Webpack5
  2. Use Happypack to pack the cache

Problem 4: Unusablehard-source-webpack-pluginThe plug-in

When using plug-ins, TypeError is reported: Cannot read property ‘tap’ of undefined solution: Webpack5 deprecated the hard-source-webpack-plugin and can use webpack’s new cache properties instead

Question 5:Conflicting values for 'process.env.NODE_ENV'An error

Error using new webpack.defineplugin to define NODE_ENV

Question 6:Can't resolve '.. /.. /core-js/object/define-propertyAn error

Solution: Add a rule to the module.

module: {

    rules: [{
        test: /\.m? js/.// fix:issue: https://github.com/webpack/webpack/issues/11467
        resolve: {
            fullySpecified: false,},... ] }},Copy the code

Question 7:merge is not a functionAn error

Const {merge} = require(‘webpack-merge’) const merge = require(‘webpack-merge’)

3. Start optimizing items

  • Webpack, as a mainstream front-end packaging tool, has complex configuration items. Just taking over optimization, I don’t know where to start:

It can be optimized from the following ideas:

Idea 1:

First determine which modules can be optimized. Webpack main configurations (Entry, Output, Resolve, module, Performance, externals, module, plugins, and others) can be optimized

Idea 2:

Use the package volume detection tool Webpack-bundle-Analyzer to analyze the package size and start optimizing

Idea 3:

Use packaging speed and each module detection plug-in speed-measure-webpack-plugin to analyze and optimize

4. Start optimizing

Use the newcacheAttributes, cache optimization (recommended)

  • Prior to Webpackage 5, you would use cache-loader to write compiled structures to the disk cache, or use babel-loader? CacheDirectory =true sets Babel compilation to be written to disk cache.

  • The cache attribute added in webpack5 will enable disk caching by default, and the compilation result will be cached in node_modules/. Cache /webpack by default.

  • When cache.type: “filesystem” is set, webpack internally enables filesystem caching and memory caching in a hierarchical manner. When reading from the cache, the memory cache is first looked at, and if it is not found, it is demoted to the file system cache. The write cache writes to both the memory cache and the file system cache.

  • The file system cache does not serialize requests to disk directly. It will not execute until the compilation process is complete and the compiler is idle. The reason for this is that serialization and disk writes take up resources, and we don’t want to delay the compilation process any further.

Resolve part optimization:

  • externals(recommended): Public CDN reference is performed for third-party packages to reduce the package size
Module.exports = {// add the react/jquery CDN address to index.html and set the external CDN reference to module.exports = {... externals: { react: 'React', jquery: 'jQuery' } ... };Copy the code
  • resolve.alias: Uses aliases to shorten reference module paths and reduce file parsing costs. (Webpack uses enhanced-resolve to resolve the file path. If the file path is relative, the file path will be spliced first, and then the module reference. Alias will not splice the file path, and the cache will be directly after the reference:Webpack.docschina.org/concepts/mo…)
Module.exports = {resolve: {alias: {'@': path.resolve(' SRC '), // @ : path.resolve(' SRC '),}}Copy the code
  • resolve.mainFields: Reduces third-party module search steps.webpack.targetThe default isbrowserslistandwebwhentargetforweborwebworkerWhen the value is["browser", "module", "main"], which can lead to unnecessary searches. Because most third-party modules are usedmainField to describe the location of the entry file, which can be set directly to:
Module.exports = {resolve: {mainFields: ['main'],},}; // exports = {resolve: {mainFields: ['main'],},};Copy the code
  • The reasonable configurationresolve.extensionsRetrieve file type
    • Keep the list values to a minimum
    • High frequency file types are suffixed first
    • Import statements in source code as far as possible write file suffixes, such asrequire(./data)To be writtenrequire(./data.json)
module.exports = {
...
    resolve:{
        extensions: ['.js', '.jsx'],
    }
}
Copy the code

Module partial optimization

  • includeandexclude: exclude the loader file from processing.
  • cache-loader(recommended): Caches the parsed files of the Loader. By default, the files are saved innode_modueles/.cache/cache-loaderUnder directory (andcacheCombined use reduces speed by about 10%.
rules: [
      {
        test: /.ext$/,
        use: ['cache-loader', ...loaders],
        include: path.resolve('src'),
      },
    ],
Copy the code
  • Set up thenoPrase(Not recommended)And:externalSimilar, but cannot coexist. The main function module skips compilation, and the difference lies in whether it needs to extract to CDN for asynchronous loading
module.exports = {
    module:{ noParse:[/jquery|chartjs/, /react.min.js$/] }
}

Copy the code

Optimization of

  • Get rid ofuglifyjs-webpack-pluginTo switch toterser-webpack-pluginDo code compression (uglifyjs-webpack-pluginThe community has lost maintenance, are 2 years ago code, although also support multi-process, but the measured effect is obviously not as good asterser-webpack-plugin)
module.exports = {
  ...
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true,
      }),
    ],
  },
  ...
};
Copy the code
  • optimize-css-assets-webpack-plugin(recommended): Compresses CSS
module.exports = {
  ...
  optimization: {
    minimize: true,
    minimizer: [
      new OptimizeCSSAssetsPlugin({
        assetNameRegExp: /\.css$/,
        safe: true,
        cache: true,
        parallel: true,
        discardComments: {
            removeAll: true,
        },

       }),
    ],
  },
  ...
};

Copy the code
  • splitChunksThe code segment(recommended): Main function is to extract common code, prevent code from being repeatedly packaged, split large JS files, merge scattered JS files)
module.exports = {
  ...
  optimization: {...splitChunks: { 
        chunks: "all".// Specify whether to pack synchronously or asynchronously
        minSize: 30000.// The chunk will be partitioned only when the chunk is larger than 30,000
        minRemainingSize: 0.maxSize: 0.// Attempts to split code based on this size
        minChunks: 1.// Specify how many times to split the code
        maxAsyncRequests: 6.maxInitialRequests: 4.automaticNameDelimiter: "~".// File generated concatenator
        cacheGroups: { 
            defaultVendors: { test: /[\\/]node_modules[\\/]/.// Meet the requirements of the group to build venders
            priority: -10.// Priority is used to determine which package to go into
            filename: "vendors".// Specify the chunks name},
            default: { 
                minChunks: 2.// Select * from *
                priority: -20.reuseExistingChunk: true.// Check if it has been referenced before,}}}... }Copy the code

RuntimeChunk: Creates an additional file or chunk to reduce the size of entry Chunk and improve performance.

module.exports = {
    ```
 optimization: {
     runtimeChunk: true
   }
}

Copy the code

The Plugin part

  • Eslint-webpack-plugin: Alternative to eslint-loader, which can be configured with auto-fix and multi-core compilation
const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  // ...
  plugins: [new ESLintPlugin()],
  // ...
};
Copy the code
  • mini-css-extract-plugin (recommended): Removes the CSS file for uploading the CDN
  • DllPlugin (Not recommended): mainly used for caching. Recommended by webpack5cache(Extract the base module that the web page depends on and package it into a DLL file. When the module to be imported exists in a DLL, the module is no longer packaged, but obtained from the DLL.)
  • Hardsourcewebpackplugin (webpack5 error, recommend to use cache instead) : Issue: github.com/mzgoddard/h…

Multithreaded packaging

  • Using Happypack: When packaging a build, Happypack creates a thread pool that splits the build task module and allocates threads to each module and its dependencies. After the processing is complete, there is a communication process that transfers the processed resources to one of the main processes of HappyPack to complete the entire build process.

  • Method of use:
    • Id: The ID associated with loader set in the configuration file will be set to the instance first for one-to-one matching between Loader and Plugin

    • Name: indicates that the plug-in type is HappyPack, which helps you quickly locate the corresponding plugin in loader and avoids the risk of errors caused by id attributes in other plug-ins

const happyThreadPool = HappyPack.ThreadPool({ size: 3 });

module: {
    rules: [{
        test: /\.js[x]?$/,
        use: [ 'happypack/loader?id=jsx']
    }]

}

plugins: [
    new HappyPack({
    id: 'jsx',
    threadPool: happyThreadPool,
    loaders: [
        {
            loader: 'babel-loader',
    },
    verbose: true,
],
...

}),
Copy the code
  • Use thread – loader
    • Note: Thread-loader cannot be used in conjunction with the Mini-CSS-extract-plugin
    • How it works: Similar to HappyPack, each time webPack parses a module, Thread-Loader assigns it and its dependencies to worker processes
    • Use:
Include: path.resolve(' SRC '), // include: path.resolve(' SRC '), // include: path.resolve(' SRC '), // [ 'babel-loader', { loader: 'thread-loader', options: { workers: 3, }, }, // 'happypack/loader', ] } ]Copy the code

Other optimizations

  • usemodeattribute
  • Js-tree-shaking: package.json set side-effect: false, remove dead code
    • Tips: Third-party packages can also be optimized, such as LoDash. By usingimport { throttle } from 'lodash-es'Instead ofimport { throttle } from 'lodash'(lodash-es willLodash Library exported asES Module, support tree shaking based on ES Modules
  • purgecss-webpack-plugin: Take CSS files tree-shaking(Recommended, CSS files may be significantly reduced)
  • The Module Federation: webpack5 new micro front-end solutions, public NPM, and post consumer component code (example: webpack.docschina.org/concepts/mo…
  • Esbuild-loader: faster than babel-loader

5. Final results

  • Packing speed before optimization:

  • Packing volume before optimization:

  • Optimized packing speed:

  • Optimized packing volume: