babel默认不转换es模块语法,需显式启用@babel/plugin-transform-modules-commonjs插件将import/export转为commonjs;配置时注意loose模式、webpack loader顺序及node_modules处理,并验证输出是否符合cjs规范。

在单体打包(如使用 Webpack、Rollup 或直接用 Babel CLI 构建)中,Babel 本身不负责模块语法转换,它默认只做语法转译(如箭头函数、解构等),而 import/export 这类 ES Module(ESM)语法需额外插件才能转为 CommonJS(CJS)。关键在于正确配置 @babel/plugin-transform-modules-commonjs,并注意与打包工具的协作关系。
明确 Babel 的职责边界
Babel 是一个语法转译器,不是模块打包器。它不会自动处理模块依赖图或 tree-shaking,只按需转换代码语法。ESM 转 CJS 属于“模块语法重写”,必须显式启用对应插件:
-
@babel/plugin-transform-modules-commonjs:将import/export语句转为require()/module.exports - 该插件默认启用
allowTopLevelThis: false,避免顶层 this 被设为 undefined(符合 CJS 行为) - 若项目同时使用 TypeScript,需确保
@babel/preset-typescript不提前剥离 import/export(它默认不处理模块格式,放心配合)
单体构建中的典型配置方式
以 Babel CLI + Webpack 单体打包为例(非 ESM 输出目标):
- 安装插件:
npm install --save-dev @babel/plugin-transform-modules-commonjs - 在
.babelrc或babel.config.js中启用:
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }]
],
plugins: [
['@babel/plugin-transform-modules-commonjs', {
allowTopLevelThis: true, // 可选,兼容某些老环境
loose: true // 可选,生成更简洁的 require 调用(不加 default 包装)
}]
]
};
⚠️ 注意:loose: true 会让 export default X 直接转成 module.exports = X,而非 module.exports.__esModule = true; module.exports.default = X,更接近原始语义,也便于 CJS 消费者直接 require()。
避开常见陷阱
以下情况会导致 ESM 未被转换,需逐一排查:
-
Webpack 已接管模块解析:若 Webpack 配置了
resolve.modules或resolve.alias,且入口是 ESM 文件,Babel 可能根本没运行到 import/export —— 确保 Babel loader 正确匹配.js文件,并在module.rules中排在其他 loader 之前 -
node_modules 默认被忽略:Babel 默认跳过
node_modules,如果依赖里含 ESM 代码且需转 CJS,要显式 include 或用babel-loader的include选项放开 -
package.json 的 "type": "module":若项目根目录有该字段,Node.js 会强制以 ESM 解析所有 .js 文件,此时即使 Babel 转了,运行时仍报错 —— 单体打包输出 CJS 时,应删掉或改用
"type": "commonjs"
验证是否生效
最直接的方法是查看 Babel 编译后的产物:
- 输入:
export const foo = 1; export default class Bar {} - 期望输出(loose: true):
module.exports.foo = 1; module.exports.default = class Bar {} - 若看到
Object.defineProperty(exports, "__esModule", { value: true }),说明用了严格模式(loose: false),CJS 消费者需通过require('x').default访问默认导出
实际打包后,可用 Node.js 直接 require() 输出文件,确认无 Cannot use import statement outside a module 报错即成功。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











