Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

The introduction

In this article, we look at tree-shaking and Code Splitting in Webpack optimization. For the basics of WebPack engineering, see webPack engineering

Tree-Shaking

Tree-shaking is the Elimination of unused Code, known as Dead Code Elimination(DCE), which was originally proposed by rollup. For example, we derived add and minus in Math.js

// math.js
export function add(a, b) {
  return a + b
}

export function minus(a, b) {
  return a - b
}
Copy the code

Then import the add method in index.js and use it

// index.js
import { add } from './math'

add(1.2)
Copy the code
// webpack.config.js
const path = require('path')

const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  mode: 'development'.devtool: 'cheap-module-source-map'.entry: {
    main: './src/index.js'
  },
  output: {
    filename: 'bundle.js'.path: path.resolve(__dirname, 'dist')},module: {
    rules: [{test: /.(jpg|png|gif)$/,
        use: {
          loader: 'url-loader'.options: {
            name: '[name]_[hash].[ext]'.outputPath: 'images/'}}}, {test: /.css$/,
        use: [
          'style-loader'.'css-loader'] {},test: /\.js$/,
        use: [
          'loader1'.'loader2',
          {
            loader: 'loader3'.options: {
              name: 'alexis'}}]}]},plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new CleanWebpackPlugin()
  ],
  resolveLoader: {
    modules: [
      'node_modules',
      path.resolve(__dirname, 'loaders')]},optimization: {
    usedExports: true}}Copy the code

Then add the following fields to package.json

"sideEffects": false
Copy the code

Run NPX webpack on the console and you can see the bundle.js generated before and after using tree-shaking

It can be seen that webpack indicates that we have used add in the Harmony export field, but does not use the (unused)minus module, and both codes contain relevant codes of add and minus. This is because tree-shaking does not remove code that is not used in the development environment. Removing code may affect the Scource-Map mapping. If we package the code for production, tree-shaking will remove Dead Code. And if we change the value of the mode field to Prodction, the optimization built into Webpack will automatically set the tree-shaking configuration, without even adding optimization

Note: Tree-shaking only supports ES Module imports, not CommonJS imports. That is, tree-shaking only checks modules imported by import, not modules imported by require

Code Splitting

If in development, for a small business code fragment modified, only change a variable name, for example, while webpack need package to generate the entire file, and the user need to download the resource files, cause waste of resources/performance, and we often introduce some public libraries, the libraries of the modified frequency is very low, Therefore, it is necessary to separate the common class libraries and allow multiple pages to take advantage of caching, thus reducing the amount of code downloaded.

Code Splitting has nothing to do with Webpack per capita, but there are plugins for Webpack that can help us quickly with Code Splitting

Copy the code
const path = require('path')

module.exports = {
  mode: 'development'.devtool: 'the eval - being - the source - the map'.entry: {
    main: './src/index.js'
  },
  output: {
    filename: '[name].js'.path: path.resolve(__dirname, 'dist')},module: {
    rules: [
      // ...]},plugins: [
    // ...].optimization: {
    usedExports: true.splitChunks: {
        chunks: "async".// Indicates the chunks to be divided. The options are async, INITIAL, and all
        minSize: 30000.// indicates that the newly separated chunk must be larger than or equal to minSize. The default value is 30000, about 30kb.
        minChunks: 1.// Indicates that a module must contain at least one chunk of minChunks. The default value is 1.
        maxAsyncRequests: 5.// represents the maximum number of simultaneous requests when modules are loaded on demand. The default is 5. If there are more than 5, no code splitting is done
        maxInitialRequests: 3.// Indicates the maximum number of simultaneous requests while loading the entry file. The default value is 3.
        automaticNameDelimiter: '~'.// Indicates the name of the chunk to be split. The default value is ~. Such as the chunk to vendors. Js
        name: true.// Set the name of chunk. The default is true. When true, splitChunks are automatically named based on the key of the chunk and cacheGroups.
        cacheGroups: {
            vendors: {
                test: /[\\/]node_modules[\\/]/,
                priority: -10.filename: 'vendor.js'
            },
        default: {
                priority: -20.reuseExistingChunk: true.// 
                filename: 'common.js'
            }
        }
    }
  }
}
Copy the code

About cacheGroups: you can configure multiple cacheGroups. Each group is conditional on test. Modules that meet the test criteria are assigned to that group. Modules can be referenced by multiple groups, and if both groups meet the criteria, they will be packaged into each group based on priority, with a higher value indicating a higher priority. By default, all modules from the node_modules directory are packaged into the vendors group, and modules shared by two or more chunks are packaged into the default group.

Run NPX webpack to see that an additional vendor.js file has been generated in the dist directory

This is because we configured Optimization so that WebPack automatically separated the external library files from the business code, automatically implementing Code Splitting for us