CommonJS
CommonJS是服務(wù)器端模塊的規(guī)范噪舀,Node.js采用了這個(gè)規(guī)范。
根據(jù)CommonJS規(guī)范蒂誉,一個(gè)單獨(dú)的文件就是一個(gè)模塊怖侦。加載模塊使用require方法篡悟,該方法讀取一個(gè)文件并執(zhí)行,最后返回文件內(nèi)部的exports對(duì)象匾寝。
例如:
// foobar.js
//私有變量
var test = 123;
//公有方法
function foobar () {
this.foo = function () {
// do someing ...
}
this.bar = function () {
//do someing ...
}
}
//exports對(duì)象上的方法和變量是公有的
var foobar = new foobar();
exports.foobar = foobar;
//require方法默認(rèn)讀取js文件搬葬,所以可以省略js后綴
var test = require('./boobar').foobar;
test.bar();
CommonJS 加載模塊是同步的,所以只有加載完成才能執(zhí)行后面的操作艳悔。像Node.js主要用于服務(wù)器的編程急凰,加載的模塊文件一般都已經(jīng)存在本地硬盤,所以加載起來比較快猜年,不用考慮異步加載的方式抡锈,所以CommonJS規(guī)范比較適用疾忍。但如果是瀏覽器環(huán)境,要從服務(wù)器加載模塊企孩,這是就必須采用異步模式。所以就有了 AMD CMD 解決方案袁稽。
AMD是"Asynchronous Module Definition"的縮寫勿璃,意思就是"異步模塊定義".
AMD設(shè)計(jì)出一個(gè)簡(jiǎn)潔的寫模塊API:
define(id?, dependencies?, factory);
第一個(gè)參數(shù) id 為字符串類型,表示了模塊標(biāo)識(shí)推汽,為可選參數(shù)补疑。若不存在則模塊標(biāo)識(shí)應(yīng)該默認(rèn)定義為在加載器中被請(qǐng)求腳本的標(biāo)識(shí)。如果存在歹撒,那么模塊標(biāo)識(shí)必須為頂層的或者一個(gè)絕對(duì)的標(biāo)識(shí)莲组。
第二個(gè)參數(shù),dependencies 暖夭,是一個(gè)當(dāng)前模塊依賴的锹杈,已被模塊定義的模塊標(biāo)識(shí)的數(shù)組字面量。
第三個(gè)參數(shù)迈着,factory竭望,是一個(gè)需要進(jìn)行實(shí)例化的函數(shù)或者一個(gè)對(duì)象。
RequireJS
RequireJS 是一個(gè)前端的模塊化管理的工具庫(kù)裕菠,遵循AMD規(guī)范咬清,它的作者就是AMD規(guī)范的創(chuàng)始人 James Burke。所以說RequireJS是對(duì)AMD規(guī)范的闡述一點(diǎn)也不為過奴潘。
RequireJS 的基本思想為:通過一個(gè)函數(shù)來將所有所需要的或者說所依賴的模塊實(shí)現(xiàn)裝載進(jìn)來旧烧,然后返回一個(gè)新的函數(shù)(模塊),我們所有的關(guān)于新模塊的業(yè)務(wù)代碼都在這個(gè)函數(shù)內(nèi)部操作画髓,其內(nèi)部也可無限制的使用已經(jīng)加載進(jìn)來的以來的模塊掘剪。
<script data-main='scripts/main' src='scripts/require.js'></script>
那么scripts下的main.js則是指定的主代碼腳本文件,所有的依賴模塊代碼文件都將從該文件開始異步加載進(jìn)入執(zhí)行奈虾。
define用于定義模塊杖小,RequireJS要求每個(gè)模塊均放在獨(dú)立的文件之中。按照是否有依賴其他模塊的情況分為獨(dú)立模塊和非獨(dú)立模塊愚墓。
獨(dú)立模塊予权,不依賴其他模塊。直接定義:
define({
method1: function(){},
method2: function(){}
});
也等價(jià)于
define(function() {
return {
method1: function(){},
method2: function(){}
}
});
非獨(dú)立模塊浪册,對(duì)其他模塊有依賴扫腺。
define([ 'module1', 'module2' ], function(m1, m2) {
...
});
或者:
define(function(require) {
var m1 = require('module1'),
m2 = require('module2');
...
});
簡(jiǎn)單看了一下RequireJS的實(shí)現(xiàn)方式,其 require 實(shí)現(xiàn)只不過是提取 require 之后的模塊名村象,將其放入依賴關(guān)系之中笆环。
require方法調(diào)用模塊
在require進(jìn)行調(diào)用模塊時(shí)攒至,其參數(shù)與define類似。
require(['foo', 'bar'], function(foo, bar) {
foo.func();
bar.func();
} );
在加載 foo 與 bar 兩個(gè)模塊之后執(zhí)行回調(diào)函數(shù)實(shí)現(xiàn)具體過程躁劣。
當(dāng)然還可以如之前的例子中的迫吐,在define定義模塊內(nèi)部進(jìn)行require調(diào)用模塊
define(function(require) {
var m1 = require( 'module1' ),
m2 = require( 'module2' );
...
});
define 和 require 這兩個(gè)定義模塊,調(diào)用模塊的方法合稱為AMD模式账忘,定義模塊清晰志膀,不會(huì)污染全局變量,清楚的顯示依賴關(guān)系鳖擒。AMD模式可以用于瀏覽器環(huán)境并且允許非同步加載模塊溉浙,也可以按需動(dòng)態(tài)加載模塊。
官網(wǎng) (http://www.requirejs.org/)
API http://www.requirejs.org/docs/api.html
RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node. Using a modular script loader like RequireJS will improve the speed and quality of your code.
為什么說like Rhino and Node. 而不是like Rhino and V8
http://www.requirejs.org/docs/node.html
Mozilla Rhino 是一個(gè)完全使用Java語言編寫的開源JavaScript引擎實(shí)現(xiàn),主要用于在java環(huán)境中執(zhí)行xxx.js 或者 js程序蒋荚。Rhino通常用于在Java程序中戳稽,為最終用戶提供腳本化能力。Rhino(犀牛)這個(gè)名字來源于O'Reilly出版的著名的“犀牛書”JavaScript: The Definitive Guide(中文譯名:JavaScript權(quán)威指南)期升。
V8使用C++開發(fā)惊奇,并在谷歌瀏覽器中使用。在運(yùn)行JavaScript之前播赁,相比其它的JavaScript的引擎轉(zhuǎn)換成字節(jié)碼或解釋執(zhí)行赊时,V8將其編譯成原生機(jī)器碼(IA-32, x86-64, ARM, or MIPS CPUs),并且使用了如內(nèi)聯(lián)緩存(inline caching)等方法來提高性能行拢。有了這些功能祖秒,JavaScript程序在V8引擎下的運(yùn)行速度媲美二進(jìn)制程序。
Node.js 是一個(gè)基于 Chrome V8 引擎的 JavaScript 運(yùn)行環(huán)境舟奠。
Node.js 使用了一個(gè)事件驅(qū)動(dòng)竭缝、非阻塞式 I/O 的模型,使其輕量又高效沼瘫。
Node.js 的包管理器 npm抬纸,是全球最大的開源庫(kù)生態(tài)系統(tǒng)。
CMD
CMD(Common Module Definition)是SeaJS 在推廣過程中對(duì)模塊定義的規(guī)范化產(chǎn)出
SeaJS
官網(wǎng) http://seajs.org/docs/
API快速參考 https://github.com/seajs/seajs/issues/266
對(duì)于依賴的模塊AMD是提前執(zhí)行耿戚,CMD是延遲執(zhí)行湿故。不過RequireJS從2.0開始,也改成可以延遲執(zhí)行(根據(jù)寫法不同膜蛔,處理方式不通過)坛猪。
CMD推崇依賴就近,AMD推崇依賴前置皂股。
//AMD
define(['./a','./b'], function (a, b) {
//依賴一開始就寫好
a.test();
b.test();
});
//CMD
define(function (requie, exports, module) {
//依賴可以就近書寫
var a = require('./a');
a.test();
...
//軟依賴
if (status) {
var b = requie('./b');
b.test();
}
});
UMD是AMD和CommonJS的糅合
AMD模塊以瀏覽器第一的原則發(fā)展墅茉,異步加載模塊。
CommonJS模塊以服務(wù)器第一原則發(fā)展,選擇同步加載就斤,它的模塊無需包裝(unwrapped modules)悍募。
這迫使人們又想出另一個(gè)更通用的模式UMD (Universal Module Definition)。希望解決跨平臺(tái)的解決方案洋机。
UMD先判斷是否支持Node.js的模塊(exports)是否存在坠宴,存在則使用Node.js模塊模式。再判斷是否支持AMD(define是否存在)绷旗,存在則使用AMD方式加載模塊喜鼓。
(function (window, factory) {
if (typeof exports === 'object') {
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
define(factory);
} else {
window.eventUtil = factory();
}
})(this, function () {
//module ...
});
SeaJs和RequireJs區(qū)別
1.定位有差異。RequireJS 想成為瀏覽器端的模塊加載器刁标,同時(shí)也想成為 Rhino / Node 等環(huán)境的模塊加載器颠通。Sea.js 則專注于 Web 瀏覽器端址晕,同時(shí)通過 Node 擴(kuò)展的方式可以很方便跑在 Node 環(huán)境中膀懈。
2.遵循的規(guī)范不同。RequireJS 遵循 AMD(異步模塊定義)規(guī)范谨垃,Sea.js 遵循 CMD (通用模塊定義)規(guī)范启搂。規(guī)范的不同,導(dǎo)致了兩者 API 不同刘陶。Sea.js 更貼近 CommonJS Modules/1.1 和 Node Modules 規(guī)范胳赌。
3.推廣理念有差異。RequireJS 在嘗試讓第三方類庫(kù)修改自身來支持 RequireJS匙隔,目前只有少數(shù)社區(qū)采納疑苫。Sea.js 不強(qiáng)推,采用自主封裝的方式來“海納百川”纷责,目前已有較成熟的封裝策略捍掺。
4.對(duì)開發(fā)調(diào)試的支持有差異。Sea.js 非常關(guān)注代碼的開發(fā)調(diào)試再膳,有 nocache挺勿、debug 等用于調(diào)試的插件。RequireJS 無這方面的明顯支持喂柒。
5.插件機(jī)制不同不瓶。RequireJS 采取的是在源碼中預(yù)留接口的形式,插件類型比較單一灾杰。Sea.js 采取的是通用事件機(jī)制蚊丐,插件類型更豐富。
https://www.douban.com/note/283566440/
OzJs