preface

Tree-shaking is one of the pitfalls of configuring Webpack. If you follow the steps in this tutorial, you will find that it takes a long time to configure Webpack but it still doesn’t work. This article is designed to solve this problem.

What is a Tree – shaking

Tree-shaking is a way for Webpack to remove redundant code.

// ~index.js
import { foo } from './content.js';

foo();


// ~content.js
export function foo() {
    alert('I am foo');
}

// Not introduced by index.js, redundant code
export function bar() {
    alert('I am bar');
}

Copy the code

The function bar is redundant code because it is not referenced. By using tree-shaking, the bar is automatically removed at packaging time, reducing the build volume of code.

How to configure

1. Set sideEffects to false in package.json

SideEffects is set to false to tell Webpack that no files have sideEffects and all files are tree-shaking. This will recognize the global imported CSS as useless and cause the global imported CSS to be removed. For example: import’./styke. CSS ‘, style. CSS will be deleted after packaging, to solve this problem, you can reset the CSS loader to true. SideEffects true indicates that files have sideEffects. Tree-shaking is not allowed.

// ~package.json
{
  "name": "webpackdemo"."version": "1.0.0"."author": "dengshangli"."license": "ISC"."description": ""."sideEffects": false. }Copy the code

2. Set sideEffects to true for csS-related loader

With sideEffects set to true, Webpack recognizes CSS code as having sideEffects, preventing tree-sahking from invalidating the global import ‘styles.css’.

// ~webpack.config.js
module.exports = {
    module: {
        rules: [{
          test: /\.css$/.use: ExtractTextPlugin.extract({
            use: [{loader: 'css-loader'.options: {
                   // Enable the CSS modularization function
                    modules: { localIdentName: '[path][name]__[local]--[hash:base64:5]' },
                    sourceMap: true,}},'postcss-loader'],}).// Recognize CSS code as a side effect to prevent tree-sahking from invalidating global import 'styles.css'
          sideEffects: true.exclude: /node_modules/,}],},... }Copy the code

3, use TerserPlugin, JS code compression plug-in

TerserPlugin is built into Webpack, there is no need to install it, and redundant code cannot be removed successfully without using TerserPlugin. Tree-shaking itself is only adding marks to redundant code, but really removing redundant code is done by using compression tools.

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

module.exports = {
  optimization: {
    // Enable JS code compression, the production environment is automatically true
    minimize: true./ / compressor
    minimizer: [
      // Tree shaking is a code compression plugin
      newTerserPlugin(), ... ] ,},... }Copy the code

4, let @babel/preset-env not compile ES6 module statements

Setting modules to false tells Babel not to compile module statements. Note that instead of compiling code, it does not compile import/export statements. This will let Babel keep our existing ES6 import/export statements, because tree-shaking only supports ES6 modular imports and exports, and CommonJs and other modular code cannot be removed successfully.

// ~.babelrc
{
  // The Babel preset is designed for easy configuration and integrates multiple plug-ins
  "presets": [["@babel/preset-env", { "modules": false}]],/ / the Babel plug-in
  "plugins": [
    "@babel/plugin-transform-runtime"]}Copy the code

Matters needing attention

  • The above configurationWebpackVersion for4.41.5, in theory,4.0That’s it
  • Tree-shakingOnly supportES6Modular import and export of
  • Tree-shakingIt only works if built in production

conclusion

This article is just a quick look at how tree-shaking is configured in Webpack. There are a lot of details I don’t have time to go into, such as setting modules to false when using @babel/preset-env to not compile ES6 module statements, The code cannot be executed in browsers that do not support import statements. If I look at the source code after construction, I find that there is no import statement.