该如何理解AMD ,CMD,CommonJS规范--javascript模块化加载学习总结

是一篇关于javascript模块化AMD,CMD,CommonJS的学习总结,作为记录也给同样对三种方式有疑问的童鞋们,有不对或者偏差之处,望各位大神指出,不胜感激。

本篇默认读者大概知道require,seajs的用法(AMD,CMD用法),所以没有加入使用语法。

1、为何而生:

这三个规范都是为javascript模块化加载而生的,都是在用到或者预计要用到某些模块时候加载该模块,使得大量的系统巨大的庞杂的代码得以很好的组织和管理。模块化使得我们在使用和管理代码的时候不那么混乱,而且也方便了多人的合作。

2、那些规范们:

      (1)、CommonJS 是一个有志于构建 JavaScript 生态圈的组织。整个社区致力于提高 JavaScript 程序的可移植性和可交换性,无论是在服务端还是浏览器端。

     a group with a goal of building up the JavaScript ecosystem for web servers, desktop and command line apps and in the browser.

    一个有目标的构建JavaScript生态系统Web服务器组,在浏览器和命令行应用程序和桌面。(他自己wiki上这么说的)

这个组织呢制定了一些规范 (可以去他们网站看看 http://www.commonjs.org/)包括CommonJS Modules/1.0 规范,我们平时所说的commonjs规范,说的就是这个了。

“The CommonJS API will fill that gap by defining APIs that handle many common application needs, ultimately providing a standard library as rich as those of Python, Ruby and Java. ”--(出自 http://www.commonjs.org/

    所以说Commonjs是一个更偏向于服务器端的规范。Node.js采用了这个规范。 根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读 取一个文件并执行,最后返回文件内部的exports对象。

        他又说了,可以用在下面这些场景  ,所以他更明显的偏向服务器端。当然你也可以把它用在浏览器里边(他们自己说可以)。

  • Server-side JavaScript applications
  • Command line tools
  • Desktop GUI-based applications
  • Hybrid applications (Titanium, Adobe AIR)

  

  (2)、AMD规范

    Commonjs解决了模块化的问题,并且可以用在浏览器中,但是Commonjs是同步加载模块,当要用到该模块了,现加载现用,这种同步机制到了浏览器里边就有问题了,加载速度啊啥的(览器同步加载模块会导致性能、可用性、调试和跨域访问等问题)。

    鉴于浏览器的特殊情况,又出现了一个规范,这个规范呢可以实现异步加载依赖模块,并且会提前加载那就是AMD规范。AMD可以作为CommonJS模块一个中转的版本只要CommonJS没有被用来同步的require调用。使用同步require调用的CommonJS代码可以被转换为使用回调风格的AMD模块加载器(https://github.com/amdjs/amdjs-api/wiki/AMD-(%E4%B8%AD%E6%96%87%E7%89%88)  (它说的)。

    

    下面是一个使用了简单CommonJS转换的模块定义(它是amd规范的一种用法):

     define(function (require, exports, module) {
       var a = require(‘a‘),
           b = require(‘b‘);

       exports.action = function () {};
     });

    所以说AMD和Commonjs是兼容的,只要稍稍调换一下调用方法就实现了同步加载(我很怀疑amd也是在commonjs基础上加了个壳,然后并没有找到其他的神马说明和支持的文字,找到了一定加到这)。

    看一下AMD规范你会发现,AMD基本都是提前说明依赖模块,然后预加载这些模块,实际上这就要求你提前想好这些依赖,提前写好,不然写代码过程中要回到开头继续添加依赖。

 

  (3)、CMD

    不知道是不是针对这个问题,淘宝的玉伯大牛搞了个seajs出来,并声称这个规范是遵循CMD规范的,然后给出了这个规范的一个连接(打开会发现draft字样)。关于这个规范呢玉伯在知乎是这么说的

      ”AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。

      CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
      类似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出。
      还有不少??

      “

     所以这个规范实际上是为了Seajs的推广然后搞出来的。那么看看SeaJS是怎么回事儿吧,基本就是知道这个规范了。

    同样Seajs也是预加载依赖js跟AMD的规范在预加载这一点上是相同的,明显不同的地方是调用,和声明依赖的地方。AMD和CMD都是用difine和require,但是CMD标准倾向于在使用过程中提出依赖,就是不管代码写到哪突然发现需要依赖另一个模块,那就在当前代码用require引入就可以了,规范会帮你搞定预加载,你随便写就可以了。但是AMD标准让你必须提前在头部依赖参数部分写好(没有写好? 倒回去写好咯)。这就是最明显的区别。

3、共生共处

  由于CommonJS是服务器端的规范,更另外两个标准实际不冲突。

  AMD在国外用的更多,当然国内也是不少的,jQuery1,7版本开始使用,Dojo在1.6版本开始用,这已经能够证明它足够牛x了。

  CMD当然也有很多人在用,但是基本都集中在国内,Seajs官网就展示了一大堆牛逼的公司在用(包括爱奇艺,腾讯微博,支付宝,淘宝等一大堆,去这看看http://seajs.org/docs/),估计小的不出名的也不计其数了,毕竟很多公司招聘都要求会seajs嘛。

所以三个规范目前都挺好(其实也主要是因为js么有自己的模块加载机制,es6出来之后不知道会怎样)。

  当我们写一个文件需要兼容不同的加载规范的时候怎么办呢,看看下面的代码。

  


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

(function (root, factory) {

    if (typeof define === ‘function‘ && define.amd) {

        // AMD

        define([‘jquery‘‘underscore‘], factory);

    else if (typeof exports === ‘object‘) {

        // Node, CommonJS之类的

        module.exports = factory(require(‘jquery‘), require(‘underscore‘));

    else {

        // 浏览器全局变量(root 即 window)

        root.returnExports = factory(root.jQuery, root._);

    }

}(thisfunction ($, _) {

    // 方法

    function a(){}; // 私有方法,因为它没被返回 (见下面)

    function b(){}; // 公共方法,因为被返回了

    function c(){}; // 公共方法,因为被返回了

     

    // 暴露公共方法

    return {

        b: b,

        c: c

    }

}));   

这个代码可以兼容各种加载规范了。

  

4、AMD和CMD的区别

下面这几点是玉伯在知乎上说的。

  1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.

  2. CMD 推崇依赖就近,AMD 推崇依赖前置

  3. AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹

  4. 还有一些细节差异,具体看这个规范的定义就好,就不多说了。

( 好吧~第四点是不多说了。。。。。。。。。)

5、AMD和CMD的一些相同

  都有difine和require,而且调用方式实际都可以添加依赖参数,也就是说都可以用提供依赖参数的方式来实现预加载依赖模块(但是不推荐因为  注意:带 id 和 deps 参数的 define 用法不属于 CMD 规范,而属于 Modules/Transport 规范。---来自:https://github.com/seajs/seajs/issues/242)。

AMD也可以在factory中使用require来现加载用到的模块,但是这个模块就不会预先加载,属于用到才加载的同步加载了。

   var a = require(‘a‘); // 加载模块a

有不妥之处,欢迎斧正。

参考资料:

http://wiki.commonjs.org/wiki/CommonJS

http://www.commonjs.org/

http://seajs.org/docs/

https://github.com/amdjs/amdjs-api/wiki/AMD

https://github.com/seajs/seajs/issues/269

https://github.com/seajs/seajs/issues/242

https://www.zhihu.com/question/20351507

http://blog.jobbole.com/49290/

http://www.cnblogs.com/qianshui/articles/4930892.html

http://blog.chinaunix.net/uid-26672038-id-4112229.html

转自:http://www.cnblogs.com/qianshui/p/5216580.html

时间: 2024-10-18 12:19:44

该如何理解AMD ,CMD,CommonJS规范--javascript模块化加载学习总结的相关文章

实现一个JavaScript模块化加载器

对任何程序,都存在一个规模的问题,起初我们使用函数来组织不同的模块,但是随着应用规模的不断变大,简单的重构函数并不能顺利的解决问题.尤其对JavaScript程序而言,模块化有助于解决我们在前端开发中面临的越来越复杂的需求. 为什么需要模块化 对开发者而言,有很多理由去将程序拆分为小的代码块.这种模块拆分的过程有助于开发者更清晰的阅读和编写代码,并且能够让编程的过程更多的集中在模块的功能实现上,和算法一样,分而治之的思想有助于提高编程生产率. 在本文中,我们将集中讨论JavaScript的模块化

利用require.js实现javascript模块化加载

这种引入很痛苦吧, <script src="1.js"></script> <script src="2.js"></script> <script src="3.js"></script> <script src="4.js"></script> <script src="5.js"></s

再唠叨JS模块化加载之CommonJS、AMD、CMD、ES6

Javascript模块化编程,已经成为一个迫切的需求.理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块. Javascript社区做了很多努力,在现有的运行环境中,实现"模块"的效果. CommonJS CommonJS定义的模块分为:  模块引用(require)    模块输出(exports)       模块标识(module) CommonJS Modules有1.0.1.1.1.1.1三个版本: Node.js.SproutCore实现了 Mo

AMD/CMD/CommonJs的区别

AMD/CMD/CommonJs是js模块化开发的标准,目前对应的实现是RequireJs/SeaJs/nodeJs. CommonJs 主要针对服务器端,AMD/CMD 主要针对浏览器端. 服务器端和浏览器端有什么区别呢? 服务器端一般采用同步加载文件,也就是说需要某个模块,服务器便停下来,等待它加载再执行,而浏览器要保证效率,需要采用异步加载,这就需要一个预处理,提前将说需要的模块并行加载好. AMD和CMD的区别,虽然都是并行加载文件,但还是有所区别,AMD是预加载,在并行加载js文件同时

FW: AMD, CMD, CommonJS和UMD

javascript 我是豆腐不是渣 4月5日发布 推荐 2 推荐 收藏 32 收藏,486 浏览 今天由于项目中引入的echarts的文件太大,requirejs经常加载超时,不得不分开来加载echarts的各个图表.但是使用echarts自带的在线构建工具生成的支持AMD 标准的模块报错,所以不得不使用echarts的全局函数,使用requirejs的shim进行加载.借此机会学习一下AMD, CMD, CommonJS和UMD各自的规范,和它们之间的区别. Javascript模块化 在了

如何构建一个微型的CMD模块化加载器

前言 前端模块化是一个老生常谈的话题,模块化的好处是不言而喻,比如易于代码复用.易于维护.易于团队开发d等云云.对于前端模块加载器,以前仅仅止步于会用的阶段,为了加深对前端模块化的理解,大概花了一周的时间来学习.调研并尝试自己实现一个简易版的符合CMD规范的加载器. 设计 加载器是按照CMD规范进行设计的,具体的CMD规范就不列出了,详情请见CMD规范. 入口函数 use(ids, callback) 模块定义函数 define(factory) 模块加载函数 require(id) 取得模块接

浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入

在<浏览器环境下JavaScript脚本加载与执行探析之defer与async特性>中,我们研究了延迟脚本(defer)和异步脚本(async)的执行时机.浏览器支持情况.浏览器bug以及其他的细节问题.而除了defer和async特性,动态脚本和Ajax脚本注入也是两种常用的创建无阻塞脚本的方法.总的来看,这两种方法都能达到脚本加载不影响页面解析和渲染的作用,但是在不同的浏览器中,这两种技术所创建的脚本的执行时机还是有一定差异,今天我们再来探讨一下通过动态脚本技术和Ajax注入的脚本在这些方

Javascript 异步加载详解(转)

本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy execution),async 属性, defer 属性 一.同步加载与异步加载的形式 1. 同步加载 我们平时最常使用的就是这种同步加载形式: <script src="http://yourdomain.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续

Javascript 异步加载详解

本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy execution),async 属性, defer 属性 一.同步加载与异步加载的形式 1. 同步加载 我们平时最常使用的就是这种同步加载形式: <script src="http://yourdomain.com/script.js"></script> 同步模式,又称阻塞模式,会阻止浏览器的后续