ES6 Modules在Chrome与Node中的兼容:export function还是module.exports?
这个问题我之前帮不少开发者梳理过,刚好可以给你一套清晰的解决思路,先拆解下你的疑问:
为什么Chrome里会报ReferenceError: module is not defined?
你应该是在模块里用了CommonJS的module.exports语法(比如module.exports = class {...}),但Chrome浏览器的原生模块环境(开启type="module"时)是不支持CommonJS的module对象的,所以会抛出这个错误。这时候确实应该用ES6的export语法,但Node.js其实已经完全支持ES6模块了,只是需要一点小配置。
Node.js如何支持ES6模块?
Node.js默认把.js文件当作CommonJS模块处理,但你可以通过两种方式让它识别ES6模块:
在项目的
package.json中添加配置:
在package.json里加一行"type": "module",这样所有.js文件都会被当作ES6模块处理:{ "type": "module" }之后你就能在Node.js文件里直接用
import导入ES6模块了。修改文件后缀为
.mjs:
如果不想改package.json,可以把你的模块文件后缀改成.mjs,Node.js会自动把这种后缀的文件当作ES6模块处理。
具体兼容方案(两种主流选择)
方案1:纯ES6模块语法(推荐,无冗余代码)
这是最简单的方式,统一用ES6的export/import语法,然后分别配置Node.js和浏览器:
第一步:编写模块(用ES6语法)
// my-module.js export class MyClass { constructor(name) { this.name = name; } greet() { console.log(`Hello, ${this.name}!`); } }
第二步:Chrome浏览器中使用
在HTML的<script>标签里加上type="module",告诉浏览器这是ES模块:
<script type="module"> import { MyClass } from './my-module.js'; const user = new MyClass('Chrome用户'); user.greet(); </script>
第三步:Node.js中使用
按照前面说的,要么在package.json加"type": "module",要么把模块改成.mjs,然后直接用import:
// node-app.js import { MyClass } from './my-module.js'; const user = new MyClass('Node.js用户'); user.greet();
运行命令:node node-app.js即可正常执行。
方案2:UMD格式(兼容旧环境/多模块规范)
如果你需要兼容一些不支持ES模块的旧浏览器,或者同时要支持CommonJS、AMD等规范,可以用UMD(Universal Module Definition)格式编写模块,它能自动适配不同的运行环境:
// my-module.js (function (root, factory) { // 适配AMD规范(比如RequireJS) if (typeof define === 'function' && define.amd) { define([], factory); } // 适配CommonJS规范(Node.js) else if (typeof module === 'object' && module.exports) { module.exports = factory(); } // 适配浏览器全局环境 else { root.MyClass = factory(); } }(typeof self !== 'undefined' ? self : this, function () { class MyClass { constructor(name) { this.name = name; } greet() { console.log(`Hello, ${this.name}!`); } } return MyClass; }));
使用方式:
- Node.js中用CommonJS的
require:const MyClass = require('./my-module.js'); - Chrome浏览器中可以直接用全局变量(不需要
type="module"):<script src="./my-module.js"></script> <script> const user = new MyClass('浏览器用户'); user.greet(); </script>
总结
如果你的项目不需要兼容特别老旧的环境,方案1的纯ES6模块+Node.js配置是最优选择,语法统一、代码简洁;如果需要覆盖更多环境,再考虑方案2的UMD格式。
内容的提问来源于stack exchange,提问作者AskYous

