【代码纪实】前端项目从 Babel v6 升级 v7

45 阅读3分钟

问题背景

近期有同事反馈一个老项目,不支持 optional chaining 语法导致项目编译不过

image.png 考虑到项目已经很久没做基础设施升级了,一直不支持新的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。

实施步骤

需要整改的配置

  1. 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"
  1. .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
      }
  ]]]
}
  1. webpack 配置
require('babel-polyfill');
// 做的事是把 babel-polyfill 直接打包最终的 js bundle 中
const appEntry = ['babel-polyfill', path.join(pathConst.moduleSrcPath, 'app.js')]

整改内容

Babel v6 升级到 v7 官方推荐的修改

  1. 使用 @babel\\\/preset-env, 不再推荐使用 stage-x
  2. 使用 babel.config.[json|js] 文件作为配置文件;
  3. babel内部包和插件包的从 babel-xxx 命名区分 改为到了@babel/xxx 这种分组区分的方式;
  4. babel官方不建议用 babel-polyfill,建议直接用 core-js。

第三方包的变化

  1. babel-plugin-component已经不维护了,需要改成babel-plugin-import

项目需求

  1. 支持 option-chaining, 集成插件"@babel/plugin-transform-optional-chaining"即可;

  2. 整改后项目运行时,发现有如下报错 image.png 调查后发现项目混用了 CJS 和 ESM,需要在config 开启 commonjs 的 modules 才行;

  3. 由于项目较老,保险起见,结合 AI 的建议,开启了语法转换

bugfixes: true,
forceAllTransforms: true,

其他

Babel官方提供的babel-upgrade 工具也尝试了,由于这个工具也不怎么维护了,给的建议偏旧,不适宜当下了,建议结合 AI 建议自行整改。

整改结果

  1. 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",
  1. 使用 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"],
  ]
};

  1. 移除 webpack 配置中 babel-polyfill 的注入,改为如上Babel自动注入 core-js
 useBuiltIns: "usage",
 corejs: 3

解决结果

至此 babel 升级完成,既满足了项目需求,也为以后支持更多JS语法打好了基础。

参考文档

  1. 官方升级 Babel V7 的文档
  2. # babel-plugin-import与babel-plugin-component的区别与联系
  3. # 正确使用 @babel/preset-env