Previous articles:

  • Relearn webpack4 principle analysis

  • Relearn webpack4 basics

  • Re-learn webpack4 loader development

  • Relearn webpack4 plugin development

  • Webpack plug-in development second open cache plug-in

  • Relearn webpack4 packaging libraries and components

Optimization of construction speed

  • Speed analysis: speed-measure-webpack-plugin
  • You can view the execution time for each Loder and plug-in
  • Red text means too long, yellow is ok, green is OK
module.exports = smg.wrap(webpackConfig)
Copy the code

wepback4 vs wepback3

  • Webpack uses V8, for of replaces forEach, Map and set replaces Object, includes replaces indexOf, and so on
  • The default is the faster MD4 hash algorithm
  • Webpack AST can be passed directly from the Loader to the AST, reducing parsing time
  • A string scheme is used to replace regular expressions, which are slow to perform operations

Multi-process/multi-instance build

Thread-loader (recommended: wepback4)

  • Each time wepback parses a module, Thread-Loader assigns it and its dependencies to the worker thread
module: {
  rules: [{test: /.js$/.// include: path.resolve('src'),
      use: [
        {
          loader: 'thread-loader'.options: {
              workers: 3 // Number of CPU cores * 2-1}},'babel-loader',]}]},Copy the code

Happypack (used by Wepback3, no longer maintained)

// Create a shared process pool containing four child processes
const happyThreadPool = HappyPack.ThreadPool({ size: 4 });
module: {
    rules: [{test: /\.js$/.// pass processing of.js files to the HappyPack instance with id Babel
        use: ['happypack/loader? id=happybabel'].exclude: /node_modules/}, {// Pass the processing of the.css file to the HappyPack instance with the id CSS
        test: /\.css$/,
        use: ['happypack/loader? id=happycss']},]},plugins: [
    new HappyPack({
      id:"happybabel".loaders: ['babel-loader? cacheDirectory'].threadPool:happyThreadPool,
      cache:true.verbose:true
    }),
    new HappyPack({
      id: 'happycss'.// loaders: ['style-loader','css-loader','postcss-loader'],
      loaders: [{loader: 'style-loader'},
        {loader: 'css-loader'.options: {minimize: false.importLoaders:1}},
        {loader: 'postcss-loader'.options: {config: {path: path.resolve(__dirname, '.. /postcss.config.js')}}}],threadPool: happyThreadPool,
    }),
]
Copy the code

parallel-webpack

  • Never used…

Multi-process/multi-instance: parallel compression

Terser-webpack-plugin Enables the PARALLEL parameter (recommended for wepback4).

  • Supports ES6 compression
module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: true./ / multi-threaded
        cache: true / / cache}})]},Copy the code

Uglifyjs-wepback-plugin

  • ES6 compression is not supported
plugins: [
  new UglifyJsPlugin({
    uglifyOptions: {
      warning: false.parse: {},
      compress: {},
      mangle: true.outpu: null.// ...
    },
    parallel: true})]Copy the code

Mode 3: Parallel-ugliffe -plugin

  • ES6 compression is not supported
module.exports = {
  plugins: [
    new ParallelUglifyPlugin({
      uglifyJS: {
        output: {
          beautify: false,
          comments: false
        },
        compress: {
          warnings: false,
          drop_console: ture,
          collapse_vars: true,
          reduce_vars: true
        }
      }
    })
  ]
}
Copy the code

Caching: Speed up secondary builds (better for development environments or statically packaged servers)

The following several ways to use at the same time, the effect of leverage

  • Babel-loader enables caching (‘babel-loader? cacheDirectory=true’)
  • TerserPlugin enables caching (cache: true)
{
  test: /\.(js|jsx)$/,
  exclude: '/(node_modules)/'.use: [{loader: 'thread-loader'.options: {
          workers: 3 // Number of CPU cores * 2-1}},// here this code
    'babel-loader? cacheDirectory=true']}Copy the code
  • Use cache-loader or hard-source-webpack-plugin (highly recommended, who knows?)
  • 12 s – > 7 s
plugins: [
  new HardSourceWebpackPlugin()
]
Copy the code

Reduce file search scope

  • Optimize the resolve.modules configuration (reduce the module search hierarchy)
  • Optimize the resolve.mainfields configuration
  • Optimize the resolve.extensions configuration
  • Use Aliases wisely
// webpack
resolve: {
  modules: [path.resolve(__dirname, '.. /node_modules')].// Restricted to the project directory, no longer up to the global lookup
  mainFields: ['main'].// Read package.json main field, entry file
  extensions: ['.js'.'.jsx'].// omit the suffix
  alias: {
    'react': path.resolve(__dirname, '.. /node_modules/react/umd/react.production.min.js'),
    'react-dom': path.resolve(__dirname, '.. /node_modules/react-dom/umd/react-dom.production.min.js'),}}Copy the code

Experimental results: the optimization of 0.3 seconds



Package volume optimization

Package analysis tool

  • webpack-bundle-analyzer
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
plugins: [
  new BundleAnalyzerPlugin({ port: 3011 }) // The default is port 8888
]
Copy the code

Further subcontracting: precompile the resource module DLL

  • React, react-dom, redux, and react-Redux base packages 🈴️ into a single file
  • Method: The DLLPlugin is used for subcontracting, and the DllReferencePlugin references manifest.json
  • Advantages: Development and production environments can skip parsing and packaging like React, speeding up hot updates and packaging

1. Create webpack. Dev. Js

const path = require('path');
const webpack = require('webpack');

module.exports = {
  mode: 'none'.context: __dirname,
  entry: {
    vendor: [
      'react'.'react-dom'.'react-router-dom'.'mobx-react'.'mobx'.'rc-pagination'.'react-topbar-progress-indicator'.'simditor']},output: {
    filename: '[name]_[hash].dll.js'.path: path.join(__dirname, '.. /dist/dll'),
    library: '[name]_[hash]' // Must be the same as the name in the DllPlugin below
  },
  resolve: {
    extensions: ['.js'.'jsx'.'.json'],},plugins: [
    new webpack.DllPlugin({
      name: '[name]_[hash]'.path: path.join(__dirname, '.. /dist/dll'.'[name]-manifest.json'),
      context: __dirname
    })
  ]
};
Copy the code

2. Generate DLL

"scripts": {
  "dll": "rimraf ./dist && webpack --config ./build/webpack.dll.js",
},
npm run dll
Copy the code

3. Import in webpack.config.js

const dllJson = require('.. /dist/dll/vendor-manifest.json')
plugins: [
  new webpack.DllReferencePlugin({
    manifest: dllJson
  })
]
Copy the code

4. HTML dynamically introduces XXXX.dll. Js

const dllJson = require('.. /dist/dll/vendor-manifest.json')
new HtmlWebpackPlugin({
  filename: 'index.html'.template: resolve(__dirname, '.. /src/index.html'),
  // CDN is used in the online environment, but I think the development environment should use DLL
  vendor: './dll/' + dllJson.name + '.dll.js'
})

/ / HTML template
DLL. Js must be referenced before any other js
<body>
  <div id="app"></div>
  <script type="text/javascript" src="<%= htmlWebpackPlugin.options.vendor %>"></script>
</body>
Copy the code

5. Execute the NPM run build and find that the packages that are split are not entered into the business code, as expected

Narrow your Build goals

tree shaking

  • Js-tree-shaking, Webpack4 mode=production Automatically handles ES6 modules
  • Css-purgecss-webpack-plugin is a plugin that traverses the code and identifies the CSS that has been used. It cannot be used independently, but needs to be used in conjunction with the Mini-CSs-extract-plugin
plugins: [
  new MiniCssExtractPlugin({
    filename: `${cf.css}/[name].[contenthash:5].css`,}).// css: tree-shaking
  new PurgecssPlugin({
    paths: glob.sync(`${PATHS.src}/ * * / * `,  { nodir: true})}),]Copy the code

Dynamic Polyfill

  • Based on official self-built Polyfill service: Polyfill Service
  • The browser accesses the Service and issues different polyfills based on the UserAgent
  • The Polyfill service implements loading polyfills on demand
<script src="https://polyfill.io/v3/polyfill.js"></script>
Copy the code

In this paper, the code

The end of the whole

After a week of reorganizing my thoughts on webpack4 over the years, it’s time to say goodbye to Webpack4 and hope not to see it again…

Webpack 5 beckons, read webPack 5 source code, come to a conclusion: all webpack techniques and add-ons before V5, loader… All abandoned, MY f * * king heart broken, no more jokes…

Stay tuned for webpack5

He’s coming, he’s coming, he’s coming with the green hat

Join us at ❤️

Bytedance Xinfoli team

Nice Leader: Senior technical expert, well-known gold digger columnist, founder of Flutter Chinese community, founder of Flutter Chinese community open source project, well-known developer of Github community, author of dio, FLY, dsBridge and other well-known open source projects

We look forward to your joining us to change our lives with technology!!

Recruitment link: job.toutiao.com/s/JHjRX8B