前端

JavaScript模块化规范 (CommonJS, AMD, UMD, ESM)

本文将简单探讨四种主要的JavaScript模块化规范: CommonJS, AMD, UMD 和 ESM。

1. CommonJS

CommonJS最初是为服务器端JavaScript设计的, 现在在Node.js中广泛使用。

核心概念:

  • 每个文件都被视为一个模块
  • 使用require()函数导入模块
  • 使用module.exportsexports导出模块

示例:

// math.js function add(a, b) { return a + b; } module.exports = { add: add }; // main.js const math = require('./math'); console.log(math.add(2, 3)); // 输出: 5

工作原理:

  1. require()函数同步加载模块
  2. 模块在第一次被require时执行,之后缓存结果
  3. 模块代码在本地作用域中执行,不会污染全局作用域

2. AMD (Asynchronous Module Definition)

AMD设计用于浏览器环境, 支持异步加载模块。

核心概念:

  • 使用define()函数定义模块
  • 使用require()函数加载模块

示例:

// math.js define([], function() { return { add: function(a, b) { return a + b; } }; }); // main.js require(['math'], function(math) { console.log(math.add(2, 3)); // 输出: 5 });

工作原理:

  1. define()函数定义模块,可以指定依赖
  2. require()函数异步加载模块及其依赖
  3. 所有依赖加载完成后,执行回调函数

3. UMD (Universal Module Definition)

UMD旨在创建同时兼容AMD和CommonJS的模块。

核心概念:

  • 通过判断运行环境来决定使用哪种模块系统
  • 可以在浏览器和Node.js中使用

示例:

(function(root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); } else if (typeof exports === 'object') { // CommonJS module.exports = factory(require('jquery')); } else { // 浏览器全局变量 root.returnExports = factory(root.jQuery); } }(this, function($) { return { // 模块方法 }; }));

工作原理:

  1. 检测当前环境支持的模块系统
  2. 根据环境使用相应的模块定义方式
  3. 允许同一模块在不同环境中使用

4. ESM (ECMAScript Modules)

ESM是JavaScript的官方标准模块系统, 在现代浏览器和Node.js中得到支持。

核心概念:

  • 使用import语句导入模块
  • 使用export语句导出模块
  • 支持静态分析, 允许树摇优化

示例:

// math.js export function add(a, b) { return a + b; } // main.js import { add } from './math.js'; console.log(add(2, 3)); // 输出: 5

浏览器中使用设置 type="module":

<script type="module" src="main.js"></script>

工作原理:

  1. 模块在编译时静态解析
  2. 导入和导出在文件顶层进行
  3. 模块只执行一次,结果被多个导入共享

总结

目前来将,ESM (ECMAScript Modules) 和 CommonJS 是现在使用最广泛的两种模块化方案。 前端开发正在逐渐向ESM过渡, 因为它是官方标准, 且支持Tree Shaking。 后端开发(Node.js)也在慢慢采用ESM, 但由于历史原因, CommonJS仍然广泛使用。

Previous
闭包的理解 - 备忘