Tree Shaking 在打包的時(shí)候去除掉沒有用到的代碼祝钢。
想要實(shí)現(xiàn) Tree Shaking 的功能觅闽,必須保證各個(gè)模塊都采用 es6-module 語法來進(jìn)行導(dǎo)入和導(dǎo)出。
有些第三方庫不是采用 es6-module 語法來編寫模塊席揽,則該庫無法 Tree Shaking判呕。
如果使用 Babel 的話品嚣,這里有一個(gè)小問題,因?yàn)?Babel 的預(yù)案(preset)默認(rèn)會將任何模塊類型都轉(zhuǎn)譯成 CommonJS 類型求冷。修正這個(gè)問題也很簡單瘤运,不是在 .babelrc 文件中就是在 webpack.config.js 文件中設(shè)置 modules: false 就好了。
對于 import() 動態(tài)引入的模塊匠题,無法進(jìn)行 Tree Shaking拯坟。
配置
production 模式下,webpack 自動幫你配置好 optimization 選項(xiàng)韭山,你不用做任何配置就能夠 Tree Shaking郁季。非 production 模式下,需要手動配置 optimization 選項(xiàng)钱磅,才能夠 Tree Shaking梦裂。
相關(guān)配置選項(xiàng):
- optimization.minimize
- optimization.minimizer
- optimization.usedExports
- optimization.sideEffects
optimization.usedExports: true
optimization.sideEffects: true
標(biāo)記未引用代碼(dead code)
optimization.minimize: true
刪除未引用代碼,并壓縮代碼
optimization.minimizer: []
指定代碼壓縮引擎
optimization.minimize
是否使用壓縮插件來壓縮生成的 bundle 代碼盖淡。
在 production 模式中 minimize 默認(rèn)為 true年柠。
module.exports = {
optimization: {
minimize: true
}
}
optimization.minimizer
配置壓縮插件,只有 minimize 為 true 的時(shí)候褪迟,配置 minimizer 才有用冗恨。
如果不配置該選項(xiàng),則 webpack 4 默認(rèn)采用 terser-webpack-plugin
插件味赃,并且自動配置 terser-webpack-plugin
插件的 options 選項(xiàng)派近。安裝 webpack 4 的時(shí)候會自動安裝 terser-webpack-plugin
,因此不需要 npm i -D terser-webpack-plugin
洁桌。
如果想要自己配置 terser-webpack-plugin
插件的 options 選項(xiàng)渴丸,需要手動配置 optimization.minimizer 選項(xiàng)。
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin(options)
]
}
}
還可以使用其他插件,例如使用 CssMinimizerPlugin 插件來壓縮 css 代碼
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin()谱轨,
new CssMinimizerPlugin()
]
}
}
通過 '...' 表明使用系統(tǒng)默認(rèn)的 TerserPlugin 插件以及默認(rèn)配置
module.exports = {
optimization: {
minimize: true,
minimizer: [
'...'戒幔,
new CssMinimizerPlugin()
]
}
}
optimization.usedExports
webpack 在打包文件的過程中,為未使用的 export 代碼添加 /* unused harmony export */
這樣的注釋土童。
在 production 模式中 usedExports 默認(rèn)為 true诗茎。
module.exports = {
optimization: {
usedExports: true
}
}
optimization.sideEffects
一個(gè) es6 模塊如果只是 export 一些變量以及函數(shù),則該模塊沒有副作用献汗。
如果一個(gè) es6 模塊除了 export 一些變量和函數(shù)敢订,還做了其他的操作,比如定義了全局變量罢吃,或者寫入日志等等楚午,例如 import '@babel/polyfill' 這個(gè)模塊,這個(gè)模塊并沒有 export 變量尿招,而是直接定義了全局變量矾柜,因此該模塊有副作用。
有副作用的模塊不能夠 tree shaking就谜,因?yàn)殡m然你的代碼里面沒有用到有副作用模塊 export 的變量怪蔑,但是也不能刪除,因?yàn)槟切┐a可能會定義全局變量或者其他副作用丧荐。你刪除了就不會定義全局變量或者其他副作用了缆瓣。
如果一個(gè)包里面所有 es 模塊都沒有副作用,那么可以在 package.json
的 sideEffects: false
指定虹统,來告知 webpack 它可以安全地刪除未用到的 export弓坞。
{
"name": "your-project",
"sideEffects": false
}
如果你的代碼確實(shí)有一些副作用,可以改為提供一個(gè)數(shù)組:
{
"name": "your-project",
"sideEffects": ["./src/some-side-effectful-file.js"]
}
optimization.sideEffects
字段表明 webpack 是否會關(guān)注各個(gè)庫中的 package.json
文件的 sideEffects
字段窟却。
在 production 模式中 sideEffects 默認(rèn)為 true。
module.exports = {
optimization: {
sideEffects: true
}
}
實(shí)例
production 模式下
production 模式下呻逆,自動實(shí)現(xiàn) Tree Shaking
module.exports = {
mode: 'production'
}
非 production 模式下
none 和 development 模式下夸赫,需要配置 optimization.minimize
optimization.usedExports
optimization.sideEffects
,才能實(shí)現(xiàn) Tree Shaking
module.exports = {
mode: 'none',
optimization: {
minimize: true,
usedExports: true,
sideEffects: true
}
}
Tree Shaking 第三方庫
如果你想要對庫進(jìn)行 Tree Shaking咖城,首先要記住的注意點(diǎn)還是前面所說的:使用 ES6 模塊茬腿。然而許多庫并不一定使用 ES6 模塊,比如 lodash 就是這樣宜雀。因此我們需要安裝 lodash-es 來代替 lodash切平。
npm i lodash-es
import { join } from lodash-es
join(['hello', 'webpack'], ' ')