babel 默认不转换esm语法,需配置@babel/preset-env与modules选项(如'commonjs')才能转为commonjs;动态import()和顶层await需额外插件;默认导出转换依赖interop机制;最终兼容性还需运行时环境或打包工具配合。

Babel 本身 不直接转换 ESM(import/export)语法为 CommonJS(require/module.exports),它默认保留原生 ESM 语句。真正实现向后兼容(如适配 Node.js 旧版本或打包工具限制)需要显式配置插件和预设,并配合运行时环境或打包流程协同工作。
ESM 转换依赖 @babel/preset-env + 模块插件
Babel 的核心规则由 preset-env 控制,它根据目标环境(targets)自动决定是否转换模块语法:
- 若
targets.node或targets.browsers支持原生 ESM(如 Node.js ≥12.20、Chrome ≥61),import/export默认不转换,仅做语法降级(如箭头函数、解构) - 若目标环境不支持 ESM(如 Node.js 10 或 IE11),且配置了
modules: 'commonjs'(或'amd'、'umd'),Babel 才会把export编译为module.exports,import编译为require() -
modules: 'auto'(默认值)会根据打包器提示(如检测到 Webpack 5+)保留 ESM,避免破坏其 Tree-shaking
动态 import() 和顶层 await 需单独处理
这些是 ESM 的扩展特性,不属基础模块语法,需额外启用:
-
import()动态导入:需开启@babel/plugin-syntax-dynamic-import(语法识别),实际转换依赖打包器(如 Webpack 分包)或插件(如@babel/plugin-transform-dynamic-import可转为Promise.resolve().then(() => require()),但有局限) - 顶层
await:需@babel/plugin-syntax-top-level-await启用语法,Babel 仅作解析;执行仍需环境支持(Node.js ≥14.8 或打包器包裹为异步 IIFE)
默认导出(export default)的转换较特殊
CommonJS 没有“默认导出”概念,Babel 的转换策略会影响互操作性:
- 当
modules: 'commonjs'时:export default foo→module.exports = foo;import x from './mod'→const x = require('./mod') - 但若模块同时含命名导出(
export const a = 1),Babel 会生成module.exports.__esModule = true并用Object.defineProperty暴露default和命名属性,以兼容 Babel/webpack 的 ESM 模拟机制 - 这种输出在纯 Node.js
require()中可能无法直接获取默认值(需require('./mod').default),除非启用interop: true(默认开启)并配合@babel/plugin-transform-modules-commonjs的兼容逻辑
真实兼容性不止靠 Babel,还需环境配合
Babel 输出的 CommonJS 代码仍需运行时支持:
- Node.js 中使用
.cjs后缀或"type": "commonjs"的package.json,否则 ESM 文件即使被 Babel 转换,也可能因文件扩展名或 package 类型被强制按 ESM 解析 - 若目标是浏览器旧环境,仅靠 Babel 转换不够,必须通过 Webpack/Rollup 打包,将模块依赖图整合为单个 IIFE 或 UMD 包
- 混合模块(既有 ESM 又有 CJS 依赖)时,Babel 不处理外部依赖的格式,需靠打包器或
resolve.extensions等配置协调
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











