前端模块化之旅(二):CommonJS、AMD和CMD

前端模块化之旅二.jpg

继续前篇,各种模块化规范开始推出,其中比较突出的是服务器端的 CommonJS 规范,它是 Nood.JS 在实践中推出的,也是首先采用 JS 模块化概念的语言,跳出了浏览器;进而出现了浏览器环境的模块化方案 AMD和CMD。

CommonJS Modules/1.0

CommonJS 规范是服务器端的模块化的规范,是 Nood.js 在实践中推出的,Nood.js 也是首先采用 js 模块化的;

它规定一个单独的文件就是一个模块,一个模块中存在一个自由变量 require,这是个函数,用于加载模块:

  • 这个 require 函数接受一个模块标识符,返回外部模块所输出的 API;
  • 如果出现依赖闭环(dependency cycle),那么外部模块在被它的传递依赖(transitive dependencies)所 require 的时候可能并没有执行完成;在这种情况下,"require"返回的对象必须至少包含此外部模块在调用require函数(会进入当前模块执行环境)之前就已经准备完毕的输出。
  • 如果请求的模块不能返回,那么"require"必须抛出一个错误。

在一个模块中,会存在一个名为 exports 的自由变量,这是一个对象,模块可以在执行的时候把自身的API加入到其中,用于定义模块,导出给其他地方使用;

exports 对象是输出模块变量的唯一方式。

参照下面的一个例子:

//math.js
exports.add = function(a,b){
    var c = a + b;
    return c;
}

//index.js
var add = require('math').add;//
console.log(add(1,1));//2

math.js中将 add 函数绑定到模块中的 exports 对象中,之后在 index.js 模块中用 require 方法加载了 math.js 模块,并调用该模块中的 add 函数。

AMD

Asynchronous Module Definition,即异步的模块定义,是浏览器端的模块化规范,是 RequireJS 在推广过程中对模块定义的规范化产出。

与服务器端的模块化规范 CommonJS 不同,AMD 的模块加载是异步的,因为是浏览器端,所以势必要是异步的(浏览器同步加载模块会导致性能、可用性、调试和跨域访问等问题)。因为模块异步加载时不会影响后面程序的执行,前面总结过 js 异步的情况,依赖某些模块的语句均放置在回调函数中,等待模块加载完成后再执行;

AMD 规范只定义了一个函数 define ,是一个全局变量,如下定义一个模块的语法:

define(id?, dependencies?, factory);
  • id:模块的名字,如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字;

  • dependencies:模块的依赖,已被模块定义的模块标识的数组字面量。依赖参数是可选的,如果忽略此参数,它应该默认为 ["require", "exports", "module"]。然而,如果工厂方法的长度属性小于3,加载器会选择以函数的长度属性指定的参数个数调用工厂方法。

  • factory:模块的工厂函数,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。

参照下面的一个例子:

define('myModule',['jQuery','types/Employee'],function($,Employee){//定义模块myModule,引入依赖jQuery,types/Employee
     function Programmer(){
            //do something
        };
        Programmer.prototype = new Employee();
        return Programmer;  //return Constructor
})

CMD

Common Module Definition,即通用模块定义,是浏览器端的模块化规范,是 SeaJS 在推广过程中对模块定义的规范化产出。

如下定义一个模块的语法:

define(factory)
  • factory 为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。factory 方法在执行时,默认会传入三个参数:require、exports 和 module.

AMD 是依赖关系前置,提前执行;CMD 是类似于 CommonJS 那样 按需加载,延迟执行

//CMD recommanded
define(function(require, exports, module){
    var a = require('a');
    a.doSomething();
    var b = require('b');
    b.doSomething();    // 依赖就近,延迟执行
});

//AMD recommanded
define(['a', 'b'], function(a, b){
    a.doSomething();    // 依赖前置,提前执行
    b.doSomething();
});

明显看出和 AMD 不同,模块定义时已不用立马引入依赖,而是运行到需要时候再加载,根据顺序执行,这样更像是 CommonJS 的风格,让人感觉也像是同步加载似的。但实际上 CMD 内部处理是对文件做了一个词法的解析,在还没执行的时候,解析出所需的依赖,并不是真正的同步。


参考:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容