参考文档
Tree Shaking 在打包的时候去除掉没有用到的代码。
想要实现 Tree Shaking 的功能,必须保证各个模块都采用 es6-module 语法来进行导入和导出。
有些第三方库不是采用 es6-module 语法来编写模块,则该库无法 Tree Shaking。
如果使用 Babel 的话,这里有一个小问题,因为 Babel 的预案(preset)默认会将任何模块类型都转译成 CommonJS 类型。修正这个问题也很简单,不是在 .babelrc 文件中就是在 webpack.config.js 文件中设置 modules: false 就好了。
对于 import() 动态引入的模块,无法进行 Tree Shaking。
配置
production 模式下,webpack 自动帮你配置好 optimization 选项,你不用做任何配置就能够 Tree Shaking。非 production 模式下,需要手动配置 optimization 选项,才能够 Tree Shaking。
相关配置选项:
- optimization.minimize
- optimization.minimizer
- optimization.usedExports
- optimization.sideEffects
optimization.usedExports: true
optimization.sideEffects: true
标记未引用代码(dead code)
optimization.minimize: true
删除未引用代码,并压缩代码
optimization.minimizer: []
指定代码压缩引擎
optimization 配置选项
optimization.minimize
是否使用压缩插件来压缩生成的 bundle 代码。
在 production 模式中 minimize 默认为 true。
module.exports = {
optimization: {
minimize: true
}
}
optimization.minimizer
配置压缩插件,只有 minimize 为 true 的时候,配置 minimizer 才有用。
如果不配置该选项,则 webpack 4 默认采用 terser-webpack-plugin
插件,并且自动配置 terser-webpack-plugin
插件的 options 选项。安装 webpack 4 的时候会自动安装 terser-webpack-plugin
,因此不需要 npm i -D terser-webpack-plugin
。
如果想要自己配置 terser-webpack-plugin
插件的 options 选项,需要手动配置 optimization.minimizer 选项。
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin(options)
]
}
}
还可以使用其他插件,例如使用 CssMinimizerPlugin 插件来压缩 css 代码
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin(),
new CssMinimizerPlugin()
]
}
}
通过 '...' 表明使用系统默认的 TerserPlugin 插件以及默认配置
module.exports = {
optimization: {
minimize: true,
minimizer: [
'...',
new CssMinimizerPlugin()
]
}
}
optimization.usedExports
webpack 在打包文件的过程中,为未使用的 export 代码添加 /* unused harmony export */
这样的注释。
在 production 模式中 usedExports 默认为 true。
module.exports = {
optimization: {
usedExports: true
}
}
optimization.sideEffects
一个 es6 模块如果只是 export 一些变量以及函数,则该模块没有副作用。
如果一个 es6 模块除了 export 一些变量和函数,还做了其他的操作,比如定义了全局变量,或者写入日志等等,例如 import '@babel/polyfill' 这个模块,这个模块并没有 export 变量,而是直接定义了全局变量,因此该模块有副作用。
有副作用的模块不能够 tree shaking,因为虽然你的代码里面没有用到有副作用模块 export 的变量,但是也不能删除,因为那些代码可能会定义全局变量或者其他副作用。你删除了就不会定义全局变量或者其他副作用了。
如果一个包里面所有 es 模块都没有副作用,那么可以在 package.json
的 sideEffects: false
指定,来告知 webpack 它可以安全地删除未用到的 export。
{
"name": "your-project",
"sideEffects": false
}
如果你的代码确实有一些副作用,可以改为提供一个数组:
{
"name": "your-project",
"sideEffects": ["./src/some-side-effectful-file.js"]
}
optimization.sideEffects
字段表明 webpack 是否会关注各个库中的 package.json
文件的 sideEffects
字段。
在 production 模式中 sideEffects 默认为 true。
module.exports = {
optimization: {
sideEffects: true
}
}
实例
production 模式下
production 模式下,自动实现 Tree Shaking
module.exports = {
mode: 'production'
}
非 production 模式下
none 和 development 模式下,需要配置 optimization.minimize
optimization.usedExports
optimization.sideEffects
,才能实现 Tree Shaking
module.exports = {
mode: 'none',
optimization: {
minimize: true,
usedExports: true,
sideEffects: true
}
}
Tree Shaking 第三方库
如果你想要对库进行 Tree Shaking,首先要记住的注意点还是前面所说的:使用 ES6 模块。然而许多库并不一定使用 ES6 模块,比如 lodash 就是这样。因此我们需要安装 lodash-es 来代替 lodash。
npm i lodash-es
import { join } from lodash-es
join(['hello', 'webpack'], ' ')