CommonJS,AMD和RequireJS的关系?

我仍然对CommonJS,AMD和RequireJS感到困惑。 即使阅读了很多。

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

CommonJS,asynchronous模块定义(AMD)和RequireJS之间有什么关系? RequireJS是否实现了CommonJS模块定义? 如果是,AMD又是什么?

RequireJS实现AMD API (源代码) 。

CommonJS是一个定义模块的方法,通过exports对象的帮助来定义模块的内容。 简而言之,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()函数来获取依赖关系,一个exportsvariables来导出模块内容和一个模块标识符(描述了与这个模块有关的模块的位置)依赖关系( 来源 )。 CommonJS有各种各样的实现,包括你提到的Node.js。

CommonJS并不是特别为浏览器而devise的,所以它不适合浏览器环境( 我真的没有这方面的资源 – 它只是说到处都是,包括RequireJS站点)。显然,这有点做asynchronous加载等

另一方面,RequireJS实现了AMD,它是为了适应浏览器环境( 源 )而devise的。 显然,AMD最初是从CommonJS Transport格式衍生出来的,并发展成为自己的模块定义API。 因此两者之间的相似之处。 AMD的新function是define()函数,它允许模块在加载之前声明它的依赖关系。 例如,定义可以是:

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

所以,CommonJS和AMD是JavaScript模块定义API,它们有不同的实现,但都来自同一个起源。

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

为了让你更加迷惑,RequireJS在作为AMD实现时提供了一个CommonJS包装器,所以CommonJS模块几乎可以直接导入与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的一部分是模块规范。 Node.js和RingoJS是服务器端JavaScript运行时,是的,他们都实现了基于CommonJS模块规范的模块。

AMD (asynchronous模块定义)是模块的另一个规范。 RequireJS可能是AMD最受欢迎的实现。 CommonJS的一个主要区别是,AMD指定模块asynchronous加载 – 这意味着模块并行加载,而不是通过等待加载完成阻塞执行。

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

简短的答案是:

CommonJSAMD是关于如何在javascript应用程序中声明模块及其依赖关系的规范(或格式)。

RequireJS是符合AMD的脚本加载器库, curljs是另一个例子。

CommonJS兼容:

采取从Addy Osmani的书 。

 // 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兼容:

 // 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 } }); 

其他地方的模块可以用于:

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

一些背景:

实际上, CommonJS不仅仅是一个API声明,它只是其中的一部分。 AMD最初是作为CommonJS列表中模块格式的草案规范起草的,但是没有达成充分的共识,并且格式的进一步发展转移到了amdjs组 。 围绕哪种格式更好的说法表明,CommonJS试图覆盖更广泛的关注点,并且考虑到它的同步性,它更适合于服务器端开发,鉴于其asynchronous特性,AMD更适合于客户端(浏览器)开发事实上它源于Dojo的模块声明实现。

资料来源:

  • RequireJS – 为什么AMD?
  • Addy Osmani – 学习JavaScriptdevise模式 – 现代模块化JavaScriptdevise模式

引用

AMD

  • 一种浏览器优先的方法
  • selectasynchronous行为并简化向后兼容性
  • 它没有任何文件I / O的概念。
  • 它支持对象,函数,构造函数,string,JSON和许多其他types的模块。

CommonJS

  • 一种服务器优先的方法
  • 假定同步行为
  • 覆盖更广泛的关注点,如I / O,文件系统,承诺等等。
  • 支持未包装的模块,它可以感觉到更接近ES.next / Harmony规范,释放你的AMD执行的define()包装。
  • 只支持对象作为模块。

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

事情是JavaScript不提供这个。 Chrome和FF的最新浏览器版本甚至没有。

但是,JavaScript中是否有关键字来调用另一个JavaScript模块?

这个问题可能会让很多人彻底崩溃,因为答案是否定的


在ES5(2009年发布)中,JavaScript没有像importincluderequire这样的关键字。

ES6节省了一天(2015年发布)提出导入关键字( 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意味着模块将从Node.js加载。 Node.js将处理从系统级文件读取到包装函数到模块中的所有内容。

因为在JavaScript中,函数是代表模块的唯一包装。

我对CommonJS和AMD很困惑?

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