原文連接: 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
下面修改下 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 除了能設置 boolean 值, 還能夠設置爲數組, 傳遞須要保留反作用的代碼文件(例如: "./src/polyfill.js") 或者傳遞模糊匹配符(例如: "src/**/*.css")
sideEffects: boolean | string[]
複製代碼
實際項目中, 一般並不能簡單的設置爲 "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 配置是以文件爲維度的, 只要你配置了文件具有反作用, 即使你只用了該文件中沒有反作用的那部分功能, 仍然會將反作用保留
好比將 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 模塊尤其重要. 使用中要特別注意聲明的正確性