本文将介绍 JS、ESM 和 UMD 这三种模块化规范的区别、用途和适用场景。
Node.js 原生使用的模块化规范,是为服务端设计的同步加载模块方案。
核心语法如下:
// 导出模块 (module.js)
const name = "CommonJS";
function sayHello() {
console.log(`Hello from ${name}`);
}
// 方式1:批量导出
module.exports = { name, sayHello };
// 方式2:单个导出
exports.sayHello = sayHello;
// 导入模块 (main.js)
const { name, sayHello } = require('./module.js');
sayHello(); // 输出: Hello from CommonJS特点:
同步加载,运行时加载(加载整个文件,生成一个对象)。
每个文件是一个独立模块,有自己的作用域。
只能在 Node.js 环境运行,浏览器不支持(需通过 webpack 等工具转译)。
模块加载后会缓存,多次 require 只会执行一次。
ES6 官方推出的模块化规范,兼顾浏览器和服务端,是模块化的未来趋势。
核心语法:
// 导出模块 (module.js)
export const name = "ES Modules";
export function sayHello() {
console.log(`Hello from ${name}`);
}
// 默认导出(一个模块只能有一个默认导出)
export default { name, sayHello };
// 导入模块 (main.js)
// 方式1:按需导入
import { name, sayHello } from './module.js';
// 方式2:导入默认导出
import moduleObj from './module.js';
// 方式3:动态导入(返回 Promise)
import('./module.js').then(module => {
module.sayHello();
});特点:
异步加载,编译时加载(静态分析,可做 Tree-Shaking 优化)。
浏览器原生支持(需在 script 标签加 type="module"):
<script type="module" src="main.js"></script>Node.js 中需将文件后缀改为 .mjs,或在 package.json 中设置 "type": "module"。
支持导入导出单个变量,无需加载整个模块。
通用模块化规范,是 CJS/AMD/ 全局变量的兼容方案,让模块能在浏览器、Node.js 等所有环境运行。
核心语法:
(function (root, factory) {
// 判断是否是 Node.js 环境(CJS)
if (typeof module === 'object' && module.exports) {
module.exports = factory();
}
// 判断是否是 AMD 环境(浏览器异步加载)
else if (typeof define === 'function' && define.amd) {
define([], factory);
}
// 浏览器全局变量
else {
root.MyModule = factory();
}
})(this, function () {
// 模块核心逻辑
const name = "UMD";
function sayHello() {
console.log(`Hello from ${name}`);
}
return { name, sayHello };
});特点:
跨环境兼容,是 “万能模块”,常用于第三方库(如 jQuery、Lodash)。
体积比 CJS/ESM 大(包含兼容逻辑)。
无需用户关心运行环境,直接使用即可。
CJS:Node.js 原生模块化方案,同步加载,适合服务端。
ESM:ES6 官方模块化规范,静态加载 + 优化,是现代前端 / Node 项目的首选。
UMD:跨环境兼容方案,适合开发需要适配多环境的第三方库,缺点是体积较大。