关于javascript:CommonJS、AMD和RequireJS之间的关系?

Relation between CommonJS, AMD and RequireJS?

我对CommonJS、AMD和RequireJS仍然很困惑。即使读了很多书。

我知道CommonJS(以前叫ServerJS)是一个组,用于在浏览器外部使用该语言时定义一些JavaScript规范(即模块)。CommonJS模块规范有一些实现,比如node.js或ringojs,对吧?

CommonJS、异步模块定义(AMD)和RequireJS之间的关系是什么?Requirej是CommonJS模块定义的实现吗?如果是,那么AMD是什么?


RequireJS实现AMDAPI(源代码)。

CommonJS是一种在exports对象的帮助下定义模块的方法,该对象定义模块内容。简单地说,一个CommonJS实现可以这样工作:

1
2
3
4
5
6
// 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变量和一个用于要求依赖项(源)的模块标识符(描述与此模块相关的有问题的模块的位置)。CommonJS有各种实现,包括您提到的node.js。

CommonJS的设计并不是特别考虑浏览器,因此它不适合浏览器环境(我真的没有这个来源——它在任何地方都这么说,包括RequireJS站点)。显然,这与异步加载等有关。

另一方面,RequireJS实现了AMD,这是为适应浏览器环境(源代码)而设计的。显然,AMD从CommonJS传输格式的衍生产品开始,发展成为自己的模块定义API。因此两者之间有相似之处。AMD中的新功能是define()函数,它允许模块在加载之前声明其依赖项。例如,定义可以是:

1
2
3
4
define('module/id/string', ['module', 'dependency', 'array'],
function(module, factory function) {
  return ModuleContents;  
});

因此,CommonJS和AMD是具有不同实现的JavaScript模块定义API,但它们都来自相同的起源。

  • AMD更适合浏览器,因为它支持模块依赖项的异步加载。
  • RequireJS是AMD的一个实现,同时试图保持CommonJS的精神(主要在模块标识符中)。

更让人困惑的是,RequireJS虽然是一个AMD实现,但它提供了一个CommonJS包装器,这样就可以直接导入CommonJS模块来与RequireJS一起使用。

1
2
3
4
define(function(require, exports, module) {
  var someModule = require('someModule'); // in the vein of node    
  exports.doSomethingElse = function() { return someModule.doSomething() +"bar"; };
});

希望这有助于澄清问题!


CommonJS不仅仅如此,它是一个为JavaScript定义公共API和生态系统的项目。通用JS的一部分是模块规范。node.js和ringojs是服务器端的javascript运行时,是的,它们都基于commonjs模块规范实现模块。

AMD(异步模块定义)是模块的另一个规范。RequireJS可能是AMD最流行的实现。与CommonJS的一个主要区别是AMD指定异步加载模块——这意味着模块是并行加载的,而不是通过等待加载完成来阻止执行。

因此,AMD通常更多地用于客户端(在浏览器中)的JavaScript开发,而CommonJS模块通常用于服务器端。但是,您可以在任意一个环境中使用任意一个模块规范—例如,RequireJS提供了在node.js中运行的指导,browserify是一个可以在浏览器中运行的通用JS模块实现。


简短的回答是:

CommonJS和AMD是有关如何在JavaScript应用程序中声明模块及其依赖项的规范(或格式)。

RequireJS是一个与AMD兼容的脚本加载程序库,CurlJS是另一个例子。

符合CommonJS:

摘自艾迪·奥斯马尼的书。

1
2
3
4
5
6
7
8
9
10
// 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;

符合标准的AMD:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 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
    }
});

模块可用于其他地方:

1
2
3
require(["package/myModule"], function(myModule) {
    myModule.foobar();
});

一些背景:

实际上,CommonJS不仅仅是一个API声明,而且只是其中的一部分。AMD最初是作为CommonJS列表中模块格式的规范草案开始的,但是还没有达成完全一致意见,格式的进一步开发转移到了AMDJS集团。关于哪种格式更好的争论表明,CommonJS试图涵盖更广泛的关注点,考虑到其同步性,它更适合服务器端开发,考虑到其异步性,以及其根源在Dojo的模块声明中,AMD更适合客户端(浏览器)开发。关于实施。

资料来源:

  • 要求-为什么是AMD?
  • addy osmani-学习javascript设计模式-现代模块化javascript设计模式


引用

AMD:

  • 一个浏览器优先方法
  • 选择异步行为并简化向后兼容性
  • 它没有任何文件I/O的概念。
  • 它支持对象、函数、构造函数、字符串、JSON和许多其他类型的模块。

CommonJS:

  • 一个服务器优先方法
  • 假设同步行为
  • 涵盖更广泛的关注点,如I/O、文件系统、承诺等。
  • 支持未封装的模块,它可以感觉更接近es.next/harmony规范,从而释放了AMD强制使用的define()包装器。
  • 仅支持对象作为模块。

将javascript程序模块化组织成多个文件并从main js module调用child-modules是很正常的。

但Javascript并没有提供这个功能。即使是现在最新的浏览器版本的Chrome和FF也不例外。

But, is there any keyword in JavaScript to call another JavaScript module?

对于许多人来说,这个问题可能是世界彻底崩溃,因为答案是否定的。

在ES5(2009年发布)中,javascript没有像import、include或require这样的关键字。

ES6保存了建议导入关键字(https://developer.mozilla.org/en/docs/web/javascript/reference/statements/import)的日期(2015年发布),但没有浏览器实现这一点。

如果您使用Babel 6.18.0并仅使用ES2015选项

1
import myDefault from"my-module";

你会再次得到require

1
2
3
4
"use strict";
var _myModule = require("my-module");
var _myModule2 = _interopRequireDefault(_myModule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

这是因为require意味着模块将从node.js加载。node.js将处理从系统级文件读取到将函数包装到模块中的所有操作。

因为在javascript中,函数是表示模块的唯一包装器。

I'm a lot confused about CommonJS and AMD?

CommonJS和AMD都只是两种不同的技术,如何克服JavaScript的"缺陷"来智能加载模块。