Original link: github.com/yinxin630/b… Technical exchange group: fiora.suisuijiang.com/

In WebPack 2, support for ES Modules was added to enable WebPack to parse unused export content and tree-shrking it out

However, webPack will keep the code that has side effects in the module

For example, there are utils/ A.js and /utils/b.js modules in the project, and unified entry is provided through utils/index.js where module B contains a print statement, which has side effects

// utils/a.js
export function a() {
    console.log('aaaaaaaaaaaaa');
}

// utils/b.js
console.log('======== b.js ==========');
export function b() {
    console.log('bbbbbbbbbbbbbb');
}

// utils/index.js
export * from './a';
export * from './b';
Copy the code

Add the main entry app.js and reference only module A. We expect unused module B to be tree-shaking away

// app.js
import { a } from './utils';
a();
Copy the code

Let’s take a look at the result of packaging, and be sure to package in Production mode. As a result, I removed the irrelevant WebPack startup code as shown below

// output
([
  function(e, t, r) {
    'use strict';
    r.r(t),
      console.log('======== b.js =========='),
      console.log('aaaaaaaaaaaaa'); },])Copy the code

The package result does not include the B module, but the side effect code in B. js is retained, which makes sense

SideEFfects role

Modify the content of B. Js below

// utils/b.js
Object.defineProperty(Array.prototype, 'sum', {
    value: function() {
        return this.reduce((sum, num) = > sum += num, 0); }})export function b() {
    console.log([1.2.3.4].sum());
}
Copy the code

We define a new method, SUM, on the Array prototype chain, which has side effects. I then called this method in module B, but as the maintainer of module B, I wanted sum to be “pure”, used only by me, and not dependent on its implementation

Modify package.json to add field “sideEffects”: False, this field indicates that the whole project is re-compiled with “no side effects”. Expect the sum method defined in b to be tree-shaking away if b module is not used

([
  function(e, t, r) {
    'use strict';
    r.r(t), console.log('aaaaaaaaaaaaa'); },])Copy the code

As expected, the entire B module is tree-shaking off, including the code that contains side effects

As a result, sideEffects can optimize the packaging volume and to some extent reduce webpack source code analysis and speed up the packaging

You can try again with package results that reference b modules, set sideEffects to true, remove sideEffects, and so on

SideEffects configuration

In addition to Boolean values, sideEffects can be set to arrays, pass code files that need to keep sideEffects (e.g. “./ SRC /polyfill.js”) or pass fuzzy matching characters (e.g. “SRC /**/*.css”).

sideEffects: boolean | string[]
Copy the code

SideEffects Considerations

In real projects, “sideEffects”: false is usually not a simple option. Some sideEffects, such as introducing style files, need to be retained

Webpack considers all import ‘XXX’ statements to be imported but not used. If you incorrectly declare them as “no side effects “, they will be tree-shaking away, and since tree-shaking only works in production mode, It is possible that everything will still be fine when you develop locally and problems will not be discovered in time

These are all examples of “introduced, not used”

import './normalize.css';
import './polyfill';
import './App.less';
Copy the code

And correspondingly, this one doesn’t count

import icon from './icon.png';
function Icon() {
    return (
        <img src={icon} />)}Copy the code

So these files that have sideEffects, we’re going to declare them correctly, change the sideEffects value

// package.json
"sideEffects": [
  "./src/**/*.css"
]
Copy the code

In use, it is important to set the sideEffects value correctly

SideEffects limitations

SideEffects configuration is file-based, so as long as you configure the file to have sideEffects, even if you only use the part of the file that doesn’t have sideEffects, the sideEffects are retained

For example, change b.js to

Object.defineProperty(Array.prototype, 'sum', {
    value: function() {
        return this.reduce((sum, num) = > sum += num, 0); }})export function b() {
    console.log([1.2.3.4].sum());
}
export function c() {
    console.log('ccccccccccccccccccc');
}
Copy the code

In app.js only c method is introduced, b method is tree-shaking, but sum method is not

Let’s talk about what side effects mean

The first time you look at the sideEffects configuration, why declare it “sideEffects free” when the code clearly has sideEffects?

Another way to think about it is that sideEffects tells webpack that the module is safe tree-shaking, without worrying about sideEffects

The latter

SideEffects has a great impact on the WebPack build process, especially for developing NPM modules. Pay special attention to the correctness of the statement