问题背景
近期有同事反馈一个老项目,不支持 optional chaining 语法导致项目编译不过
考虑到项目已经很久没做基础设施升级了,一直不支持新的JS语法不利于后续继续维护,就决定升级Babel支持相关语法,下面是这个升级过程的记录。
问题调研
排查项目发现项目中的 babel-loader 版本是 7.x,在和 AI Chatbot 的沟通中了解到 babel-loader 7.x 对应的 babel(babel-core) 版本是 6.x,由于老项目用的 webpack 版本是 4.x,兼容的 babel-core 版本是 7.x,目前还不想考虑升级Webpack,所以考虑把 babel 从 v6 升级到 v7。
实施步骤
需要整改的配置
- package.json相关包
"devDependencies": {
"babel-core": "^6.17.0",
"babel-eslint": "^8.2.3",
"babel-loader": "7.1.4",
"babel-plugin-component": "^0.4.3",
"babel-plugin-import": "^1.13.3",
"babel-plugin-lodash": "^3.3.4",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-modules": "^0.1.1",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-preset-es2015": "^6.6.0",
"babel-preset-stage-2": "^6.18.0",
"babel-runtime": "^6.11.6",
...
"dependencies": {
"babel-polyfill": "^6.26.0"
- .babelrc 配置
{
"presets": ["es2015", "stage-2"],
"comments": true,
"plugins": [["component", [
{
"libraryName": "mint-ui",
"style": true
},
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]], "syntax-dynamic-import",
["import", [
{
"libraryName": "vant",
"style": true
}
]]]
}
- webpack 配置
require('babel-polyfill');
// 做的事是把 babel-polyfill 直接打包最终的 js bundle 中
const appEntry = ['babel-polyfill', path.join(pathConst.moduleSrcPath, 'app.js')]
整改内容
Babel v6 升级到 v7 官方推荐的修改
- 使用
@babel\\\/preset-env, 不再推荐使用stage-x; - 使用 babel.config.[json|js] 文件作为配置文件;
- babel内部包和插件包的从 babel-xxx 命名区分 改为到了@babel/xxx 这种分组区分的方式;
- babel官方不建议用 babel-polyfill,建议直接用 core-js。
第三方包的变化
项目需求
-
支持 option-chaining, 集成插件
"@babel/plugin-transform-optional-chaining"即可; -
整改后项目运行时,发现有如下报错
调查后发现项目混用了 CJS 和 ESM,需要在config 开启 commonjs 的 modules 才行;
-
由于项目较老,保险起见,结合 AI 的建议,开启了语法转换
bugfixes: true,
forceAllTransforms: true,
其他
Babel官方提供的babel-upgrade 工具也尝试了,由于这个工具也不怎么维护了,给的建议偏旧,不适宜当下了,建议结合 AI 建议自行整改。
整改结果
- package.json相关包
"devDependencies": {
"@babel/core": "^7.24.0",
"@babel/eslint-parser": "^7.24.0",
"@babel/plugin-transform-optional-chaining": "^7.25.9",
"@babel/preset-env": "^7.24.0",
"babel-loader": "^8.3.0",
"babel-plugin-import": "^1.13.8",
"babel-plugin-lodash": "^3.3.4",
"babel-plugin-transform-modules": "^0.1.1",
...
"dependencies": {
"core-js": "^3.35.0",
"@babel/runtime": "^7.24.0",
- 使用 babel.config.js 文件,符合官方推荐,也可以方便写 js 函数
module.exports = {
presets: [
["@babel/preset-env", {
targets: {
browsers: ["iOS >= 9", "ChromeAndroid >= 37"]
},
modules: "commonjs",
bugfixes: true,
forceAllTransforms: true,
useBuiltIns: "usage",
corejs: 3
}]
],
comments: true,
plugins: [
"@babel/plugin-transform-optional-chaining",
"lodash",
[
"import",
{
"libraryName": "mint-ui",
"customName": (name) => `mint-ui/lib/${name}`,
"customStyleName": (name) => `mint-ui/lib/${name}/style.css`
},
"import-mint"
],
[
"import",
{
"libraryName": "element-ui",
"customName": (name) => `element-ui/lib/${name}.js`,
"customStyleName": (name) => `element-ui/lib/theme-chalk/${name}.css`
},
"import-element"
],
["import", { "libraryName": "vant", "style": true }, "import-vant"],
]
};
- 移除 webpack 配置中 babel-polyfill 的注入,改为如上Babel自动注入 core-js
useBuiltIns: "usage",
corejs: 3
解决结果
至此 babel 升级完成,既满足了项目需求,也为以后支持更多JS语法打好了基础。