我仍然对CommonJS, AMD和RequireJS很困惑,即使在阅读了很多之后。

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

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


当前回答

引用

AMD:

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

CommonJS:

一种服务器优先的方法 假设同步行为 涵盖更广泛的问题集,如I/O,文件系统,承诺等。 支持未包装模块,感觉更接近ES。next/Harmony规范,将你从AMD强制的define()包装器中解放出来。 只支持对象作为模块。

其他回答

将JavaScript程序模块组织成几个文件并从主js模块调用子模块是很正常的。

问题是JavaScript没有提供这个。即使在最新版本的Chrome和FF浏览器中也没有。

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

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


在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意味着模块将从Node.js加载。Node.js将处理从系统级文件读取到将函数包装到模块中的所有事情。

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

我对CommonJS和AMD很困惑?

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

AMD

在JavaScript中引入将JavaScript项目扩展到多个文件 主要用于基于浏览器的应用程序和库 流行的实现是RequireJS, Dojo Toolkit

CommonJS:

它是处理大项目中大量功能、文件和模块的规范 ServerJS的初始名称是Mozilla在2009年1月引入的 2009年8月更名为CommonJS,以显示api更广泛的适用性 最初的实现是服务器,nodejs,基于桌面的库

例子

upper.js文件

exports.uppercase = str => str.toUpperCase()

main.js文件

const uppercaseModule = require('uppercase.js')
uppercaseModule.uppercase('test')

总结

AMD——最古老的模块系统之一,最初由require.js库实现。 CommonJS -为Node.js服务器创建的模块系统。 UMD -一个多模块系统,建议作为一个通用系统,兼容AMD和CommonJS。

资源:

https://exploringjs.com/es6/ch_modules.html#sec_modules-in-javascript 维基百科

CommonJS不仅仅是这样——它是一个为JavaScript定义通用API和生态系统的项目。CommonJS的一部分是Module规范。Node.js和RingoJS是服务器端JavaScript运行时,是的,它们都实现了基于CommonJS模块规范的模块。

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

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

引用

AMD:

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

CommonJS:

一种服务器优先的方法 假设同步行为 涵盖更广泛的问题集,如I/O,文件系统,承诺等。 支持未包装模块,感觉更接近ES。next/Harmony规范,将你从AMD强制的define()包装器中解放出来。 只支持对象作为模块。

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()函数来获取依赖项,一个exports变量来导出模块内容,还有一个模块标识符(描述了与该模块相关的有问题的模块的位置),用于要求依赖项(源)。CommonJS有各种实现,包括你提到的Node.js。

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

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

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中使用。

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