Babel配置会影响Tree Shaking效果吗?
我最近在优化项目打包体积,发现即使用了ES Module,Webpack的Tree Shaking好像也没生效。我怀疑是不是Babel的配置有问题,因为看到有人说Babel会把import/export转成CommonJS,导致Tree Shaking失效。
我现在的Babel配置里用了@babel/preset-env,但没特别设置modules选项。比如下面这段代码,明明只用了add,但打包后subtract也被包含进去了:
// utils.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
// index.js
import { add } from './utils';
console.log(add(1, 2));
是不是要加什么配置才能让Babel保留ES Module语法,不破坏Tree Shaking?
@babel/preset-env默认把ES Module转成了CommonJS,Webpack就无法做静态分析了。默认情况下,
modules选项是"auto",在Webpack环境下它会自动转成CommonJS,这就把import/export全换成require了,Tree Shaking自然就失效了。解决办法很简单,在Babel配置里显式关掉模块转换:
或者如果你用的是
.babelrc.js或babel.config.js,写法类似:这样Babel就不会动你的import/export了,Webpack就能正常做Tree Shaking。
不过要注意,关掉modules转换后,Babel就不会处理模块语法了,但其他特性(比如async/await、class属性等)还是会正常转译,只要你的
targets配置合理就行。另外提醒一句,Webpack 4默认开启Tree Shaking的前提是
mode设为production,或者手动配置optimization.usedExports = true,确认下你的Webpack配置里没漏掉这个。更好的写法是把Babel和Webpack的配置都统一管理,避免这种隐式坑,比如用
babel-loader时加上presets: [['@babel/preset-env', { modules: false }]],这样一目了然,也不容易忘。