webpack 4 新增 sideEffects 配置的做用和注意事项

原文连接: github.com/yinxin630/b…
技术交流群: fiora.suisuijiang.com/css

在 webpack 2 版本, 增长了对 ES Module 的支持, 使得 webpack 可以分析出未使用的 export 内容, 而后将其 tree-shrking 掉webpack

可是模块中那些具有反作用的代码, webpack 会将其保留git

举一个例子, 项目中存在 utils/a.js 模块和 /utils/b.js 模块, 并经过 utils/index.js 提供统一入口
其中 b 模块包含一条打印语句, 是具备反作用的github

// 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';
复制代码

添加主入口 app.js, 只引用 a 模块, 咱们指望未使用的 b 模块被 tree-shaking 掉web

// app.js
import { a } from './utils';
a();
复制代码

咱们看一下打包后的结果, 注意要在 production 模式下打包. 结果以下所示, 我去掉了无关的 webpack 启动代码npm

// output
([
  function(e, t, r) {
 'use strict';
    r.r(t),
      console.log('======== b.js =========='),
      console.log('aaaaaaaaaaaaa');
  },
])
复制代码

打包结果中, 不包含 b 模块, 可是 b.js 中的反作用代码被保留了, 这是合乎情理的json

sideEFfects 做用

下面修改下 b.js 的内容数组

// 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());
}
复制代码

咱们在 Array 原型链上定义了一个新方法 sum, 这是具备反作用的. 而后在 b 模块中调用了该方法, 可是做为 b 模块的维护者, 我又但愿 sum 是"纯粹"的, 只被我使用, 外部并不依赖它的实现安全

修改 package.json, 新增字段 "sideEffects": false, 该字段代表整个工程是"无反作用"的
从新调用 webpack 编译, 期待在 b 模块没被使用的状况下, b 中定义的 sum 方法也被 tree-shaking 掉, 结果以下app

([
  function(e, t, r) {
 'use strict';
    r.r(t), console.log('aaaaaaaaaaaaa');
  },
])
复制代码

如指望那样, 整个 b 模块都被 tree-shaking 掉了, 包括包含反作用的代码

因此, sideEffects 能够优化打包体积, 而且必定程度上能够减小 webpack 对源码分析过程, 加快打包速度

你能够再试试引用 b 模块、sideEffects 值设为 true、去掉 sideEffects 等状况的打包结果

sideEffects 配置

sideEffects 除了能设置 boolean 值, 还能够设置为数组, 传递须要保留反作用的代码文件(例如: "./src/polyfill.js") 或者传递模糊匹配符(例如: "src/**/*.css")

sideEffects: boolean | string[]
复制代码

sideEffects 注意事项

实际项目中, 一般并不能简单的设置为 "sideEffects": false, 有些反作用是须要保留的, 好比引入样式文件

webpack 会认为全部 import 'xxx' 语句是仅引入而未使用, 若是你错误的将其声明成了"无反作用", 它们就会被 tree-shaking 掉, 而且因为 tree-shaking 仅在 production 模式生效, 本地开发时可能一切还是正常的, 并不能及时发现问题

下面这些都是"仅引入而未使用"的例子

import './normalize.css';
import './polyfill';
import './App.less';
复制代码

相应的, 下面这种就不算

import icon from './icon.png';
function Icon() {
    return (
        <img src={icon} /> ) } 复制代码

这些有反作用的文件, 咱们要正确声明, 修改 sideEffects 值

// package.json
"sideEffects": [
  "./src/**/*.css"
]
复制代码

在使用中, 务必要正确设置 sideEffects 值

sideEffects 局限性

sideEffects 配置是以文件为维度的, 只要你配置了文件具有反作用, 即使你只用了该文件中没有反作用的那部分功能, 仍然会将反作用保留

好比将 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());
}
export function c() {
    console.log('ccccccccccccccccccc');
}
复制代码

app.js 中仅引入 c 方法, b 方法会被 tree-shaking, 但 sum 方法不会

再谈"反作用"的含义

初次看到 sideEffects 配置可能会很奇怪, 代码明明是有反作用的, 为何要声明它是"无反作用"呢?

其实能够换个角度来想, sideEffects 是通知 webpack 该模块是能够安全的 tree-shaking 的, 无需关心其反作用

后话

sideEffects 对 webpack 构建过程有着很大影响, 对开发 npm 模块尤其重要. 使用中要特别注意声明的正确性

相关文章
相关标签/搜索