Webpack 中 tree shaking 功能实现的局限性
举一个 tree shaking 的栗子:
boy.js
1 | // boy.js |
index.js
1 | // index.js |
构建结果:
bundle.js
1 | const name = 'name'; |
可以看到,age 因为没有被使用,所以在最终的构建结果中被自动删除了,这就是 tree shaking,帮助我们删除未使用过的代码。
相对于 dce 的成熟,tree shaking 是一个新提出的概念。因为它的实现,依赖于 es module 的规范定义,可以使我们有机会对 js 进行依赖的静态分析。
如何在 webpack 中使用
webpack 2 后的版本会自动 开启 tree shaking,但是它的实际生效是有条件的。
- 代码必须是 es module 格式。
若引用 external 模块,它的 package.json 中必须标明该模块不含副作用( sideEffects 为 false)。可以参考:https://github.com/webpack/webpack/tree/master/examples/side-effects
这就要求我们必须使用 es module 来写代码,也要保证代码传给 webpack 时,代码格式没被 babel 自动转为 commonjs。因为 babel-preset-env 会自动开启 commonjs 模块转换,会把 es module 转为 commonjs,我们需要把 babel-preset 配置为 module: false 。
webpack 在 tree shaking 的 bug
还是上面的例子,我们把 boy.js 增加一个方法:
1 | // boy.js |
index.js 维持不变
1 | const name = 'name'; |
可以发现构建产物发生了变化:
bundle.js
1 | const logger = { |
因为 index.js 中没有引用 getAge 方法,我们希望 getAge 方法和它所依赖的 logger 都不要打入最终的 bundle 中,结果可以看到 logger 被打了进来,webpack 不能进行更深一层的副作用依赖分析。
可以使用 https://github.com/vincentdchan/webpack-deep-scope-analysis-plugin 这个插件来修复这个问题。