babel在node.js环境中需显式配置@babel/plugin-transform-modules-commonjs插件并设loose: true,才能将es6模块正确转为简洁的commonjs格式,否则会保留es模块语法或生成冗余__esmodule标记。

在单体打包(如纯 Node.js 环境)中,Babel 将 ES6 模块(import/export)转为 CommonJS(require/module.exports),关键在于配置正确的预设和插件,尤其要启用模块转换能力。
用 @babel/preset-env + 显式模块插件
默认情况下,@babel/preset-env 在 node: 'current' 目标下会跳过模块语法转换(因现代 Node 已原生支持 ES 模块)。必须额外启用模块转换插件:
- 安装插件:
npm install --save-dev @babel/plugin-transform-modules-commonjs - 在
babel.config.js中明确配置:module.exports = { presets: [ ['@babel/preset-env', { targets: { node: 'current' } }] ], plugins: [ ['@babel/plugin-transform-modules-commonjs', { allowTopLevelThis: true, loose: true }] ] }; -
loose: true是重点:它让export default X直接生成module.exports = X,而非带__esModule标记的包装形式,更利于 CJS 消费者直接require()使用
避免常见陷阱
仅靠 presets: ['@babel/preset-env'] 不足以转换模块——它默认保留 import/export。即使目标是 Node,也必须显式启用模块转换插件。
- 不写
plugins或漏掉@babel/plugin-transform-modules-commonjs→ 输出仍是 ES 模块语法,Node 运行时报Cannot use import statement outside a module - 没设
loose: true→export default会生成两行:module.exports.__esModule = true和module.exports.default = X,CJS 用户需写require('x').default才能取值,不够直观 -
modules: false(常用于 webpack 场景)会禁用所有模块转换 → 此场景下绝对不能用
验证转换结果
写一个简单 ES 模块文件 src/math.js:
export const add = (a, b) => a + b;<br>export default (x) => x * 2;
运行 npx babel src --out-dir lib 后,lib/math.js 应类似:
Object.defineProperty(exports, "__esModule", {<br> value: true<br>});<br>exports.add = void 0;<br>const add = (a, b) => a + b;<br>exports.add = add;<br>exports.default = (x) => x * 2;
若启用了 loose: true,则变为更简洁的:
exports.add = (a, b) => a + b;<br>exports.default = (x) => x * 2;
此时其他 CommonJS 文件可直接 const math = require('./lib/math'),并访问 math.add 和 math.default(或解构 const { add } = require('./lib/math'))
不需要 Browserify 或 Webpack
这是纯 Babel 单体转换,适用于 Node.js 后端、CLI 工具或构建脚本等无需浏览器兼容的场景。只要输出是 CJS 语法,Node 就能直接运行,无需额外打包工具。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











