本文梳理了主流的 JS 模块化方案。
ESM(ES Modules)
现代 JavaScript 推荐方式。支持静态分析、异步加载和 Tree Shaking。
使用环境:
node
(需要加 "type": "module"
或 .mjs
后缀)、浏览器
(现代浏览器原生支持)
语法:
// 导入模块
import React from 'react';
import {foo, bar} from './myLib';
// 导出模块
export default function() {
// your Function
};
export const function1() {...};
export const function2() {...};
CJS(CommonJS)
Node.js 默认的模块系统,同步加载。
使用环境:
Node.js
(默认支持)
语法:
// 导入模块
const React = require('react');
const { foo, bar } = require('./myLib');
// 导出模块
module.exports = function () {
// your Function
};
exports.function1 = () => {...};
exports.function2 = () => {...};
AMD(Asynchronous Module Definition)
异步加载,常与 RequireJS 搭配。
使用环境:
浏览器
,通常配合 RequireJS
语法:
define(['react', './myLib'], function (React, myLib) {
function function1() {...}
function function2() {...}
return {
function1,
function2,
};
});
UMD(Universal Module Definition)
为了解决多种加载环境兼容问题(AMD、CJS、浏览器全局),常用于库的发布。
使用环境:
兼容 Node.js
、浏览器
、AMD
加载器(如 RequireJS)
语法:
((global, factory) => {
//如果 当前的上下文有define函数,并且AMD 说明处于AMD 环境下
if (typeof define === "function" && define.amd) {
define(["moduleA"], factory);
} else if (typeof exports === "object") {
//commonjs
let moduleA = require("moduleA");
modules.exports = factory(moduleA);
} else {
global.moduleA = factory(global.moduleA); //直接挂载成 windows 全局变量
}
})(this, moduleA => {
//本模块的定义
return {};
});
IIFE(Immediately Invoked Function Expression)
立即执行函数表达式,早期模拟模块私有作用域的做法。
使用环境:
浏览器
,适用于简单模块或早期模块化场景
语法:
(function foo() {
console.log("立即执行函数");
})();
SystemJS
动态模块加载器,支持多种模块格式,常用于微前端等场景。
使用环境:
浏览器
(需要引入 SystemJS 库)
语法:
// 动态加载模块
System.import("/js/main.js")
.then(() => {
// 执行初始化逻辑
})
.catch(error => {
// 处理加载错误
});
总结
方案 | 适用环境 | 优点 | 缺点 |
---|---|---|---|
ESM | Node/浏览器 | 标准、静态、原生支持 | 兼容性需注意 |
CJS | Node | 简单、生态丰富 | 仅同步、非浏览器友好 |
AMD | 浏览器 | 异步、依赖明确 | 语法繁琐 |
UMD | 通用 | 兼容性强 | 实现复杂 |
IIFE | 浏览器 | 简单 | 无依赖管理 |
SystemJS | 浏览器 | 动态、格式兼容性强 | 依赖库、体积大 |