RequireJS和CommonJS的区别

19

我在想这些代码片段之间的区别是什么。

var $ = require('jquery');
var _ = require('underscore');
var BackBone = require('backbone');

require(['jquery','underscore','backbone'],function ($, _, BackBone){
    //code goes here
})

对我来说两者都可以,但不确定上述两种方式背后是否有任何目的。


3
我认为第一个是CommonJS语法,另一个是AMD语法,更常见于使用requireJS的文件中。 - Andy
1
关于一些背景,您可以阅读RequireJS文档,讨论CommonJS风格(第一个代码)与AMD(第二个代码)。 - Gábor Imre
1
RequireJS类似于Browserify和Webpack,它是一个JS模块加载器。AMD是RequireJS的标准/规范,类似于CommonJS。 - Alexander Mills
2个回答

29
考虑第一个代码片段,它是采用CommonJS风格的:
var $ = require('jquery');
var _ = require('underscore');
var BackBone = require('backbone');

这些调用是同步的调用:当 require 返回时,它返回您请求的模块。CommonJS require 调用是同步的。有一个提案支持异步形式的 require,但据我所知,它还没有超出提案阶段。Node.js 曾经有 require.async,但已被删除。不过有一个 实现了它。使用这个包看起来很像使用 AMD 风格的模块。
现在,考虑第二个片段,它是以 AMD 风格编写的:
require(['jquery','underscore','backbone'],function ($, _, BackBone){
    //code goes here
})

由于RequireJS实现了AMD类型的模块系统,上述代码可与RequireJS一起使用。这个require调用是异步的,正如其名称“异步模块定义(AMD)”所示。你不能依赖require的返回值来获取模块值,而必须使用回调函数。define调用的工作方式类似,但除了要求模块外还定义了一个模块。
现在,如果你使用RequireJS,它提供了一些工具,允许你在定义模块时使用任一风格,这样你就可以像这样定义一个模块:
define(['jquery','underscore','backbone'],function ($, _, BackBone){
    //code goes here
});

或者使用更像CommonJS习惯用法的方式,如下所示:

define(function (require) {
    var $ = require('jquery');
    var _ = require('underscore');
    var BackBone = require('backbone');
    //code goes here
});

我可以帮助将CommonJS风格的模块转换为RequireJS使用的模块:只需像上面那样用define调用包装即可。有一个工具可以帮助进行转换。

在幕后,RequireJS读取第二种形式的回调代码并创建依赖项列表,以便最终被解释为:

define(['require', 'jquery','underscore','backbone'], function (require) {
    var $ = require('jquery');
    var _ = require('underscore');
    var BackBone = require('backbone');
    //code goes here
})

虽然 AMD 是异步的,但在回调函数中的 require 调用是同步的,这可能令人惊讶。这是 RequireJS 支持 CommonJS 风格的一部分。RequireJS 支持一种同步的 require 调用,但有以下注意事项:如果在同步 require 调用之前模块已经被定义,则同步 require 返回模块的值,否则它会立即失败。也就是说,它不会尝试加载模块。因为 RequireJS 将使用我上面展示的 CommonJS 风格的模块定义解释为实际上在 define 参数中列出了依赖项,所以这些模块保证在进行同步 require 调用时已经被加载。
除了可以在 RequireJS 中使用 CommonJS 模块(只要添加包装器),还可以在像 Node.js 这样的 CommonJS 环境中使用为 RequireJS 设计的模块。例如,我使用 node-amd-loader 在 Node.js 中加载我设计的 AMD 模块。

1
这个回答比我发的好多了。 - Achrome

1
前面这个片段遵循CommonJS规范,该规范概述了模块如何导出/传输以在其他模块中使用。
因此,您可以编写类似于以下代码的代码。

src/ExpressModule.js

var express = require('express');
// do initialization
exports.express = express;

然后你可以像这样使用它。

src/UserExpressModule.js

var express = require('./ExpressModule');
// do something else

CommonJS规范主要用于服务器端环境,并且通过扩展在Node.js中使用。

另一方面,AMD最著名的实现是RequireJS。AMD是为浏览器环境或客户端代码构建的,在这里您可以像后面的代码片段那样使用和定义模块。

一个示例用法可能是这样的:

src/main.js

requirejs.config({
    baseUrl: '../vendor'
    path: '../src'
});
require(['jquery', 'underscore', 'backbone'], function($, _, Backbone) {
    // do some client side computation here
});

你可以像这样在 index.html 中包含 main.js 文件。
<script data-main="src/main.js" src="vendor/require.js"></script>

基本上,CommonJS和AMD是用于模块化Javascript的核心规范,但它们针对不同的执行环境。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接