Babel 配置会影响 Tree Shaking 吗?
我最近在优化项目打包体积,发现即使没用的代码还是被打包进去了。明明用了 Webpack 5 的 Tree Shaking,但好像没生效。
我怀疑是不是 Babel 的配置有问题?比如我用了 @babel/preset-env,会不会把 ES6 模块转成 CommonJS,导致 Tree Shaking 失效?
我的 .babelrc 是这样配的:
{
"presets": [
["@babel/preset-env", {
"targets": "> 1%, not dead"
}]
]
}
是不是得加个 "modules": false?试过加了之后打包体积确实小了点,但不确定是不是这个原因……
在你的配置里,@babel/preset-env 默认会把模块转成 CommonJS,这就是问题所在。加上 "modules": false 是正确的方向,这样 Babel 就不会转换模块系统,保持 ES6 原汁原味,Webpack 才能正常做 Tree Shaking。
建议把 .babelrc 改成这样:
不过要注意,这个配置只适合支持 ES6 模块的环境。要是你需要兼容老浏览器,就得用动态导入或者单独打包 polyfill。我以前就遇到过这种情况,以为优化完成了,结果在 IE 上直接报错,累觉不爱。
总之,保持 ES6 模块形式对 Tree Shaking 至关重要,别忘了测试下最终打包效果。记得多看看打包后的文件,有时候还能发现其他没被摇掉的代码。
@babel/preset-env 默认会把 ES6 的 import/export 转成 CommonJS 的 require/module.exports,这样 Webpack 在静态分析时就无法判断哪些导出被使用了,Tree Shaking 自然就失效了。
你加的 "modules": false 是正确的做法,它会让 Babel 不转换模块语法,把模块转换交给 Webpack 处理。
完整配置大概是这样:
{
"presets": [
["@babel/preset-env", {
"targets": "> 1%, not dead",
"modules": false
}]
]
}
或者更规范的做法是通过 Webpack 的配置来控制,而不是依赖 Babel。现在 Webpack 5 已经能很好地处理 ES6 模块了,Babel 这边关掉模块转换是更合理的做法。
另外提醒一下,如果你的项目里用了 dynamic import 或者某些插件,可能会影响 Tree Shaking。还有确保 package.json 里 type 字段不要写成 commonjs,ES Module 环境下 Tree Shaking 效果更好。