CommonJS 以服务器端为目标环境,能够一次性把所有模块都加载到内存,而异步模块定义(AMD,
Asynchronous Module Definition)的模块定义系统则以浏览器为目标执行环境,这需要考虑网络延迟的
问题。AMD 的一般策略是让模块声明自己的依赖,而运行在浏览器中的模块系统会按需获取依赖,并
在依赖加载完成后立即执行依赖它们的模块。
AMD 模块实现的核心是用函数包装模块定义。这样可以防止声明全局变量,并允许加载器库控制
何时加载模块。包装函数也便于模块代码的移植,因为包装函数内部的所有模块代码使用的都是原生
JavaScript 结构。包装模块的函数是全局define 的参数,它是由AMD 加载器库的实现定义的。
AMD 模块可以使用字符串标识符指定自己的依赖,而AMD 加载器会在所有依赖模块加载完毕后
立即调用模块工厂函数。与CommonJS 不同,AMD 支持可选地为模块指定字符串标识符。
// ID 为’moduleA’的模块定义。moduleA 依赖moduleB,
// moduleB 会异步加载
define(‘moduleA’, [‘moduleB’], function(moduleB) {
return {
stuff: moduleB.doStuff();
};
});
AMD 也支持require 和exports 对象,通过它们可以在AMD 模块工厂函数内部定义CommonJS
风格的模块。这样可以像请求模块一样请求它们,但AMD 加载器会将它们识别为原生AMD 结构,而不是模块定义:
define(‘moduleA’, [‘require’, ‘exports’], function(require, exports) {
var moduleB = require(‘moduleB’);
exports.stuff = moduleB.doStuff();
});
动态依赖也是通过这种方式支持的:
define(‘moduleA’, [‘require’], function(require) {
if (condition) {
var moduleB = require(‘moduleB’);
}
});
通用模块定义
为了统一CommonJS 和AMD 生态系统,通用模块定义(UMD,Universal Module Definition)规范
应运而生。UMD 可用于创建这两个系统都可以使用的模块代码。本质上,UMD 定义的模块会在启动时
检测要使用哪个模块系统,然后进行适当配置,并把所有逻辑包装在一个立即调用的函数表达式(IIFE)
中。虽然这种组合并不完美,但在很多场景下足以实现两个生态的共存。
下面是只包含一个依赖的UMD 模块定义的示例(来源为GitHub 上的UMD 仓库):
(function (root, factory) {
if (typeof define === ‘function’ && define.amd) {
// AMD。注册为匿名模块
define([‘moduleB’], factory);
} else if (typeof module === ‘object’ && module.exports) {
// Node。不支持严格CommonJS
// 但可以在Node 这样支持module.exports 的
// 类CommonJS 环境下使用
module.exports = factory(require(’ moduleB '));
} else {
// 浏览器全局上下文(root 是window)
root.returnExports = factory(root. moduleB);
}
}(this, function (moduleB) {
// 以某种方式使用moduleB
// 将返回值作为模块的导出
// 这个例子返回了一个对象
// 但是模块也可以返回函数作为导出值
return {};
}));
此模式有支持严格CommonJS 和浏览器全局上下文的变体。不应该期望手写这个包装函数,它应该
由构建工具自动生成。开发者只需专注于模块的内由容,而不必关心这些样板代码。
模块加载器终将没落
随着ECMAScript 6 模块规范得到越来越广泛的支持,本节展示的模式最终会走向没落。尽管如此,
为了了解为什么选择设计决策,了解ES6 模块规范的由来仍是非常有用的。CommonJS 与AMD 之间的
冲突正是我们现在享用的ECMAScript 6 模块规范诞生的温床。
javascript基础学习系列六百一十八:异步模块定义
最新推荐文章于 2024-11-13 01:18:00 发布
本文讨论了CommonJS以服务器端为目标,一次性加载所有模块,与异步模块定义AMD的浏览器执行环境策略。介绍了AMD模块的加载机制,包括模块依赖声明和模块工厂函数。通用模块定义UMD被提出以兼容两者,随着ES6模块规范的发展,旧模式将逐渐被淘汰。
摘要由CSDN通过智能技术生成