首页 文章

CommonJS,AMD和RequireJS之间的关系?

提问于
浏览
751

我对CommonJS,AMD和RequireJS仍感到非常困惑 . 即使阅读了很多 .

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

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

5 回答

  • 193

    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并没有特别考虑到浏览器的设计,因此它不适合浏览器环境(我真的没有这方面的资源 - 它只是说到处都是,包括the RequireJS site.)显然,这与异步有关装货等

    另一方面,RequireJS实现了AMD,其设计适合浏览器环境(source) . 显然,AMD最初是作为CommonJS Transport格式的衍 生产环境 品,并发展成为自己的模块定义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"; };
    });
    

    我希望这有助于澄清事情!

  • 178

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

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

    由于这一点,AMD通常更多地用于客户端(浏览器内)JavaScript开发,而CommonJS模块通常用于服务器端 . 但是,您可以在任一环境中使用任一模块规范 - 例如,RequireJS提供directions for running in Node.jsbrowserify是可以在浏览器中运行的CommonJS模块实现 .

  • 24

    简短的回答是:

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

    RequireJS 是一个符合AMD标准的脚本加载程序库,curljs是另一个例子 .

    CommonJS兼容:

    取自Addy Osmani's book .

    // 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 group . 关于哪种格式更好地说明CommonJS试图涵盖更广泛的关注点以及它的模块声明实现的参数 .

    来源:

  • 710

    Quoting

    AMD

    • 一种浏览器优先方法

    • 选择异步行为和简化的向后兼容性

    • 它没有任何文件I / O的概念 .

    • 它支持对象,函数,构造函数,字符串,JSON和许多其他类型的模块 .

    CommonJS

    • 一种服务器优先的方法

    • 假设同步行为

    • 涵盖更广泛的关注点,例如I / O,文件系统,Promise等 .

    • 支持解包模块,它可以感觉更接近ES.next/Harmony规范,释放 AMD 强制执行的define()包装器 .

    • 仅支持对象作为模块 .

  • 12

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

    事情是JavaScript没有提供这个 . 即使在今天的Chrome和FF的最新浏览器版本中也是如此 .

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

    对于许多人来说,这个问题可能是一个完全崩溃的世界,因为答案是 No .


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

    ES6保存了 import 关键字(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import)的日期(2015年发布),但没有浏览器实现这一点 .

    如果您使用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“缺陷”来加载模块智能 .

相关问题