We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在 webpack 2 版本, 增加了对 ES Module 的支持, 使得 webpack 能够分析出未使用的 export 内容, 然后将其 tree-shrking 掉
但是模块中那些具备副作用的代码, webpack 会将其保留
举一个例子, 项目中存在 utils/a.js 模块和 /utils/b.js 模块, 并通过 utils/index.js 提供统一入口 其中 b 模块包含一条打印语句, 是具有副作用的
utils/a.js
/utils/b.js
utils/index.js
// 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 掉
app.js
// app.js import { a } from './utils'; a();
我们看一下打包后的结果, 注意要在 production 模式下打包. 结果如下所示, 我去掉了无关的 webpack 启动代码
// output ([ function(e, t, r) { 'use strict'; r.r(t), console.log('======== b.js =========='), console.log('aaaaaaaaaaaaa'); }, ])
打包结果中, 不包含 b 模块, 但是 b.js 中的副作用代码被保留了, 这是合乎情理的
b.js
下面修改下 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 是"纯粹"的, 只被我使用, 外部并不依赖它的实现
sum
修改 package.json, 新增字段 "sideEffects": false, 该字段表明整个工程是"无副作用"的 重新调用 webpack 编译, 期待在 b 模块没被使用的情况下, b 中定义的 sum 方法也被 tree-shaking 掉, 结果如下
"sideEffects": false
([ function(e, t, r) { 'use strict'; r.r(t), console.log('aaaaaaaaaaaaa'); }, ])
如期望那样, 整个 b 模块都被 tree-shaking 掉了, 包括包含副作用的代码
所以, sideEffects 可以优化打包体积, 并且一定程度上可以减少 webpack 对源码分析过程, 加快打包速度
你可以再试试引用 b 模块、sideEffects 值设为 true、去掉 sideEffects 等情况的打包结果
sideEffects 除了能设置 boolean 值, 还可以设置为数组, 传递需要保留副作用的代码文件(例如: "./src/polyfill.js") 或者传递模糊匹配符(例如: "src/**/*.css")
sideEffects: boolean | string[]
实际项目中, 通常并不能简单的设置为 "sideEffects": false, 有些副作用是需要保留的, 比如引入样式文件
webpack 会认为所有 import 'xxx' 语句是仅引入而未使用, 如果你错误的将其声明成了"无副作用", 它们就会被 tree-shaking 掉, 并且由于 tree-shaking 仅在 production 模式生效, 本地开发时可能一切仍是正常的, 并不能及时发现问题
import 'xxx'
下面这些都是"仅引入而未使用"的例子
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 配置是以文件为维度的, 只要你配置了文件具备副作用, 即便你只用了该文件中没有副作用的那部分功能, 仍然会将副作用保留
比如将 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 模块尤为重要. 使用中要特别注意声明的正确性
The text was updated successfully, but these errors were encountered:
No branches or pull requests
在 webpack 2 版本, 增加了对 ES Module 的支持, 使得 webpack 能够分析出未使用的 export 内容, 然后将其 tree-shrking 掉
但是模块中那些具备副作用的代码, webpack 会将其保留
举一个例子, 项目中存在
utils/a.js
模块和/utils/b.js
模块, 并通过utils/index.js
提供统一入口其中 b 模块包含一条打印语句, 是具有副作用的
添加主入口
app.js
, 只引用 a 模块, 我们期望未使用的 b 模块被 tree-shaking 掉我们看一下打包后的结果, 注意要在 production 模式下打包. 结果如下所示, 我去掉了无关的 webpack 启动代码
打包结果中, 不包含 b 模块, 但是
b.js
中的副作用代码被保留了, 这是合乎情理的sideEFfects 作用
下面修改下
b.js
的内容我们在 Array 原型链上定义了一个新方法
sum
, 这是具有副作用的. 然后在 b 模块中调用了该方法, 但是作为 b 模块的维护者, 我又希望sum
是"纯粹"的, 只被我使用, 外部并不依赖它的实现修改 package.json, 新增字段
"sideEffects": false
, 该字段表明整个工程是"无副作用"的重新调用 webpack 编译, 期待在 b 模块没被使用的情况下, b 中定义的 sum 方法也被 tree-shaking 掉, 结果如下
如期望那样, 整个 b 模块都被 tree-shaking 掉了, 包括包含副作用的代码
所以, sideEffects 可以优化打包体积, 并且一定程度上可以减少 webpack 对源码分析过程, 加快打包速度
你可以再试试引用 b 模块、sideEffects 值设为 true、去掉 sideEffects 等情况的打包结果
sideEffects 配置
sideEffects 除了能设置 boolean 值, 还可以设置为数组, 传递需要保留副作用的代码文件(例如: "./src/polyfill.js") 或者传递模糊匹配符(例如: "src/**/*.css")
sideEffects 注意事项
实际项目中, 通常并不能简单的设置为
"sideEffects": false
, 有些副作用是需要保留的, 比如引入样式文件webpack 会认为所有
import 'xxx'
语句是仅引入而未使用, 如果你错误的将其声明成了"无副作用", 它们就会被 tree-shaking 掉, 并且由于 tree-shaking 仅在 production 模式生效, 本地开发时可能一切仍是正常的, 并不能及时发现问题下面这些都是"仅引入而未使用"的例子
相应的, 下面这种就不算
这些有副作用的文件, 我们要正确声明, 修改 sideEffects 值
在使用中, 务必要正确设置 sideEffects 值
sideEffects 局限性
sideEffects 配置是以文件为维度的, 只要你配置了文件具备副作用, 即便你只用了该文件中没有副作用的那部分功能, 仍然会将副作用保留
比如将
b.js
修改为在
app.js
中仅引入 c 方法, b 方法会被 tree-shaking, 但 sum 方法不会再谈"副作用"的含义
初次看到 sideEffects 配置可能会很奇怪, 代码明明是有副作用的, 为什么要声明它是"无副作用"呢?
其实可以换个角度来想, sideEffects 是通知 webpack 该模块是可以安全的 tree-shaking 的, 无需关心其副作用
后话
sideEffects 对 webpack 构建过程有着很大影响, 对开发 npm 模块尤为重要. 使用中要特别注意声明的正确性
The text was updated successfully, but these errors were encountered: