即使在阅读了很多之后,我仍然对CommonJS、AMD和RequireJS感到非常困惑。
我知道CommonJS(以前称为ServerJS)是在浏览器之外使用该语言时定义一些JavaScript规范(即module)的组。CommonJSmodule规范有一些实现,比如Node.js或RingoJS,对吧?
CommonJS、异步module定义(AMD) 和RequireJS之间的关系是什么?
是RequireJS的的实现CommonJS的module定义?如果是,那么AMD是什么?
即使在阅读了很多之后,我仍然对CommonJS、AMD和RequireJS感到非常困惑。
我知道CommonJS(以前称为ServerJS)是在浏览器之外使用该语言时定义一些JavaScript规范(即module)的组。CommonJSmodule规范有一些实现,比如Node.js或RingoJS,对吧?
CommonJS、异步module定义(AMD) 和RequireJS之间的关系是什么?
是RequireJS的的实现CommonJS的module定义?如果是,那么AMD是什么?
RequireJS实现了AMD API (源代码)。
CommonJS是一种借助exports
对象定义module的方法,该对象定义了module内容。简单地说,一个 CommonJS 实现可能是这样的:
// someModule.js
exports.doSomething = function() { return "foo"; };
//otherModule.js
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
基本上,CommonJS 指定你需要有一个require()
函数来获取依赖项,一个exports
变量来导出module内容和一个module标识符(它描述了与这个module相关的问题module的位置),用于要求依赖项(源)。CommonJS 有各种实现,包括您提到的Node.js。
CommonJS 并不是专门为浏览器设计的,所以它不太适合浏览器环境(*我真的没有这方面的来源——它只是在任何地方都这么说,包括RequireJS 站点。*)显然,这有与异步加载等有关。
另一方面,RequireJS 实现了 AMD,旨在适应浏览器环境(源代码)。显然,AMD 最初是从 CommonJS Transport 格式衍生出来的,后来演变成它自己的module定义 API。因此,两者之间有相似之处。AMD 的新功能是define()
允许module在加载之前声明其依赖项的功能。例如,定义可以是:
define('module/id/string', ['module', 'dependency', 'array'],
function(module, factory function) {
return ModuleContents;
});
因此,CommonJS 和 AMD 是JavaScriptmodule定义 API,它们具有不同的实现,但都来自相同的起源。
更让您困惑的是,RequireJS 虽然是 AMD 实现,但提供了一个 CommonJS 包装器,因此几乎可以直接导入 CommonJS module以与 RequireJS 一起使用。
define(function(require, exports, module) {
var someModule = require('someModule'); // in the vein of node
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
});
CommonJS不仅如此——它是一个为 JavaScript 定义通用 API 和生态系统的项目。CommonJS 的一部分是module规范。Node.js 和 RingoJS 是服务器端 JavaScript 运行时,是的,它们都实现了基于 CommonJS Module 规范的module。
AMD(异步module定义)是另一种module规范。RequireJS可能是 AMD 最流行的实现。与 CommonJS 的一个主要区别是 AMD 指定module是异步加载的——这意味着module是并行加载的,而不是通过等待加载完成来阻止执行。
因此,AMD 通常更多地用于客户端(浏览器内)JavaScript 开发,而 CommonJS module通常用于服务器端。但是,您可以在任一环境中使用任一module规范 - 例如,RequireJS 提供了在 Node.js 中运行的指导,而browserify是可以在浏览器中运行的 CommonJS module实现。
CommonJS和AMD是关于如何在 javascript 应用程序中声明module及其依赖项的规范(或格式)。
RequireJS是一个符合 AMD 标准的脚本加载器库, curljs是另一个例子。
// package/lib is a dependency we require
var lib = require( "package/lib" );
// behavior for our module
function foo(){
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
exports.foobar = foo;
// package/lib is a dependency we require
define(["package/lib"], function (lib) {
// behavior for our module
function foo() {
lib.log( "hello world!" );
}
// export (expose) foo to other modules as foobar
return {
foobar: foo
}
});
该module可以在其他地方用于:
require(["package/myModule"], function(myModule) {
myModule.foobar();
});
实际上,CommonJS不仅仅是一个 API 声明,它只是其中的一部分。AMD 开始时是 CommonJS 列表中module格式的草案规范,但没有达成完全共识,格式的进一步开发转移到了amdjs 组。关于哪种格式更好的争论表明 CommonJS 试图涵盖更广泛的问题,并且鉴于其同步性质,它更适合服务器端开发,而 AMD 更适合客户端(浏览器)开发,因为其异步性质和事实上,它源于 Dojo 的module声明实现。
超微:
通用JS:
AMD
强制执行的 define() 包装器。将 JavaScript 程序module化组织成多个文件并child-modules
从main js module
.
问题是 JavaScript 不提供这个。即使在今天最新的 Chrome 和 FF 浏览器版本中也没有。
但是,JavaScript 中是否有任何关键字可以调用另一个 JavaScript module?
这个问题对很多人来说可能是世界彻底崩溃,因为答案是否定的。
在 ES5(2009 年发布)中,JavaScript 没有像import、include或require这样的关键字。
ES6 挽救了这一天(2015 年发布)提出了import关键字( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import),现在所有现代浏览器都支持这一点。
如果您使用 Babel 6.18.0 并且仅使用 ES2015 选项进行编译
import myDefault from "my-module";
你会require
再次得到。
"use strict";
var _myModule = require("my-module");
var _myModule2 = _interopRequireDefault(_myModule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
这是因为require
意味着module将从 Node.js 加载。Node.js 将处理从系统级文件读取到将函数包装到module中的所有事情。
因为在 JavaScript 中,函数是表示module的唯一包装器。
我对 CommonJS 和 AMD 很困惑?
CommonJS 和 AMD 只是两种不同的技术,它们如何克服 JavaScript“缺陷”以智能加载module。