883

即使在阅读了很多内容之后,我仍然对CommonJS、AMDRequireJS感到非常困惑。

我知道CommonJS(以前称为ServerJS)是一组用于定义一些JavaScript规范(即模块),当该语言在浏览器之外使用时。CommonJS模块规范有一些实现,比如Node.jsRingoJS,对吧?

CommonJS异步模块定义(AMD) 和RequireJS之间有什么关系?

RequireJSCommonJS模块定义的实现吗?如果是,那么AMD是什么?

4

6 回答 6

803

RequireJS实现了AMD API (source)

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用于导出模块内容的变量和一个模块标识符(它描述了与该模块相关的模块的位置),用于需要依赖项(source)。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更适合浏览器,因为它支持模块依赖的异步加载。
  • 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"; };
});
于 2013-05-13T13:14:08.313 回答
207

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

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

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

于 2013-05-13T13:06:50.937 回答
196

简短的回答是:

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 试图涵盖更广泛的关注点,并且鉴于其同步性质,它更适合服务器端开发,而 AMD 更适合客户端(浏览器)开发,因为它具有异步性质和事实上,它源于 Dojo 的模块声明实现。

资料来源:

于 2013-12-29T23:05:49.170 回答
29

报价

超微

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

通用JS

  • 一种服务器优先的方法
  • 假设同步行为
  • 涵盖更广泛的关注点,例如 I/O、文件系统、Promises 等。
  • 支持展开的模块,感觉更接近ES.next/Harmony规范,让您摆脱AMD强制执行的 define() 包装器。
  • 仅支持将对象作为模块。
于 2015-07-29T10:36:06.253 回答
17

将 JavaScript 程序模块化组织成几个文件并child-modulesmain js module.

问题是 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 “缺陷”以智能加载模块。

于 2016-10-30T23:50:48.920 回答
2

AMD

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

通用JS

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

例子

上层.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 兼容。

资源:

于 2020-07-14T13:05:48.747 回答