1. ES6 Modules (ESM)
现代 JavaScript 官方标准,支持静态分析和 tree-shaking。
// 导出
export const name = 'value';
export function func() {};
export default Component;
// 导入
import Component, { name } from './module.js';
import * as all from './module.js';
特点:
- 静态结构,便于优化
- 支持异步加载
- 浏览器原生支持(现代浏览器)
- 需要文件扩展名
.js
2. CommonJS (CJS)
Node.js 的默认模块系统,主要用于服务器端。
// 导出
module.exports = {
name: 'value',
func: function() {}
};
// 或
exports.name = 'value';
// 导入
const module = require('./module');
const { name } = require('./module');
特点:
- 同步加载
- 运行时动态加载
module.exports和exports指向同一对象- 每个模块有
require,module,exports,__dirname,__filename
3. UMD (Universal Module Definition)
兼容多种环境的通用模式。
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['dependency'], factory);
} else if (typeof exports === 'object') {
// CommonJS
module.exports = factory(require('dependency'));
} else {
// 浏览器全局变量
root.myModule = factory(root.dependency);
}
}(this, function(dependency) {
// 模块代码
return {
name: 'value'
};
}));
特点:
- 兼容 AMD、CommonJS 和全局变量
- 文件较大(包含兼容代码)
- 常用于库的打包
4. AMD (Asynchronous Module Definition)
主要用于浏览器端的异步加载。
// 定义模块
define(['dependency1', 'dependency2'], function(dep1, dep2) {
return {
method: function() {
return dep1.something() + dep2.something();
}
};
});
// 使用
require(['module'], function(module) {
module.method();
});
特点:
- 异步加载,适合浏览器
- RequireJS 是实现者
- 声明依赖,回调执行
对比
| 特性 | ES6 Modules | CommonJS | UMD | AMD |
|---|---|---|---|---|
| 加载方式 | 同步/异步 | 同步 | 多种 | 异步 |
| 环境 | 浏览器/Node.js | Node.js | 所有环境 | 浏览器 |
| Tree-shaking | 支持 | 不支持 | 不支持 | 不支持 |
| 静态分析 | 支持 | 不支持 | 不支持 | 部分支持 |
| 语法 | import/export | require/module.exports | 兼容语法 | define/require |
现代项目中的使用
{
"name": "@webgl2d/core",
"version": "1.0.0",
"description": "",
"main": "lib/index.cjs.js",
"module": "lib/index.es.js",
"types": "lib/index.d.ts",
"exports": {
".": {
"types": "./lib/index.d.ts",
"import": "./lib/index.es.js",
"require": "./lib/index.cjs.js",
"default": "./lib/index.umd.js"
}
},
"scripts": {
"dev": "vue-tsc -b && vite build --watch",
"build": "vue-tsc -b && vite build"
},
"type": "module",
"files": [
"lib",
"package.json"
],
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.24.0",
"dependencies": {
"gl-matrix": "^3.4.4",
"uuid": "^13.0.0",
"vite-plugin-dts": "^4.5.4"
},
"devDependencies": {
"@types/node": "^24.10.1",
"@vitejs/plugin-vue": "^6.0.1",
"typescript": "~5.9.3",
"vite": "^7.2.4",
"vue-tsc": "^3.1.4"
}
}
构建工具中的配置
// WebGL2D Core Library Vite Configuration
import { defineConfig ,type UserConfig } from "vite";
import dts from "vite-plugin-dts";
import { resolve } from "path";
let config:UserConfig = {
plugins: [
dts({
tsconfigPath: "tsconfig.app.json",
insertTypesEntry: true,
copyDtsFiles: true,
// 指定需要为哪些文件生成类型定义
include: [
"src/**/*.d.ts",
"src/**/*.vue",
"src/**/*.ts",
"index.ts",
],
}),
],
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
},
},
build: {
outDir: "lib",
lib: {
name: "WebGL2DCore",
entry: resolve(__dirname, "./index.ts"),
fileName: (format, entryName) => `${entryName}.${format}.js`,
formats: ["es", "umd", "cjs"],
},
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ["vue"],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: "Vue",
},
},
},
},
}
export default defineConfig(config);
最佳实践
-
库开发:同时提供 ES6 和 CommonJS 版本
-
现代应用:优先使用 ES6 模块
-
Node.js:
- 设置
"type": "module"使用 ES6 模块 - 或使用
.mjs扩展名表示 ES6 模块 .cjs扩展名表示 CommonJS
- 设置
-
浏览器:
<!-- ES6 模块 --> <script type="module" src="app.js"></script> <!-- 传统脚本 --> <script nomodule src="legacy.js"></script> -
动态导入(ES2020):
// 动态导入,返回 Promise const module = await import('./module.js');
选择哪种模块系统取决于:
- 目标运行环境(浏览器/Node.js)
- 是否需要向后兼容
- 构建工具的配置
- 是否需要 tree-shaking 优化