1、原理
tree shaking
是基于es module的静态分析,在编译期间就确定了模块(module)使用情况,并且配合解构赋值能够确定module中哪些方法用到了,哪些没有用到。然后对用到的和没用到的进行标记,在压缩阶段删除没有用到的部分。
2、作用
删除项目中没有用到的代码,有针对性的优化代码来达到最小的bundle size。
3、基本使用
开发环境下
webpack.config.js设置mode、optimization.usedExports、devtool属性。
module.exports = {
mode: 'development',
optimization: {
usedExports: true
},
devtool: 'inline-source-map',
entry: {
app: "./src/index.js",
},
...
}
这里设置devtool
为inline-source-map
主要是为了以源代码的方式查看export使用情况。对于未使用的export,optimization.usedExports
会添加unused harmony export square
的注释

正式环境
webpack.config.js设置mode、optimization.usedExports、devtool属性。
module.exports = {
mode: 'production',
optimization: {
usedExports: true
},
devtool: '(none)',
}
mode设置为production后会开启压缩模式,查找压缩后代码中也只是引入了使用的代码。

4、使用tree shaking的注意事项
-
使用es module的模块规范,使用解构赋值。
tree shaking是机遇es module的静态分析,所以代码必须使用esm规范。我们在业务代码中一般都会基于esm规范,但是对于第三方的插件不一定,部分第三方插件基于commonJS规范。
-
开启optimization.usedExports属性。
optimization: { usedExports: true },
该属性主要是用于产生标记,标记哪些export使用到了,哪些export没有被使用到。
-
使用压缩插件。
webpack4+ 直接将mode设置为production即可开启压缩。
-
tree shaking只能做到export级别。
如果模块导出一个对象,我们在使用时可能只使用到了对象中的几个属性或者方法,这时候是不能被tree shaking作用的。
为了更好地配合tree shaking,我们在编码过程中尽量不要export出对象使用,这样能够保证tree shaking打包成最小的bundle。
-
不需要tree shaking的模块,可以在package.json中添加
sideEffects
进行配置。如果所有的模块都不包含副作用,可以直接将该属性设置为false,来告诉webpack可以安全删除未用到的export。
如果有些模块有副作用,我们不想让webpack去删除这些export,可以在
sideEffects
中提供一个数组{ "name": "your-project", "sideEffects": [ "./src/some-side-effectful-file.js", "*.css" ] }
注意,所有导入文件都会受到 tree shaking 的影响。这意味着,如果在项目中使用类似
css-loader
*并 import 一个 CSS 文件,则需要将其添加到 side effect 列表中,以免在生产模式中无意中将它删除。
5、使用lodash-es 代替 lodash
我们在项目中可能会使用到lodash的一些功能,进而引入了整个lodash,而lodash是基于commonJS的第三方包,即使使用解构赋值也不会触发tree shaking,导致打包的bundle体积会大很多。
这里推荐使用lodash-es,lodash-es所提供的api与lodash相同,是基于ESM规范的。这里使用解构赋值的方式仅引入使用到的接口,很大程度上减小构建的bundle体积。