前端模塊規範AMD/UMD/CommonJs

.babelrc文件中的:module設置爲false,爲何會要設置成false?前端

解釋:使ES6模塊語法轉換到另外一個模塊類型(默認啓用「commonjs」)。 設置爲假則不變換模塊。或者傳入(「amd」、「umd」,「systemjs」、「commonjs」)。node

什麼是模塊?jquery

Javascript的組件生態在最近幾年的發展很給力,咱們的可選性更加普遍了。這本是一件好事,可是當多個第三方Javascript在一塊兒混合使用的時候,咱們可能會遇到一個很尷尬的問題,那就是否是全部的組件都能在一塊兒很愉快的玩耍的。git

爲了解決這個問題,兩種競爭關係的前端模塊規範(AMD和CommonJS)問世了。他們規定開發者們採用一種約定好的模式來寫代碼,以免污染整個生態系統。github

AMD規範--經過define(['加載的模塊依賴','',''], 加載完依賴的回調函數)

AMD規範,全稱」Asynchronous Module Definition」,稱爲異步模塊加載規範。通常應用在瀏覽器端。流行的瀏覽器端異步加載庫RequireJS中文網站)實現的就是AMD規範。api

下面是使用AMD規範定義一個名爲foo模塊的方式,此模塊依賴jquery,數組

1
2
3
4
5
6
7
8
// filename: foo.js
define(['jquery'], function ($) {
// methods
function myFunc(){};

// exposed public methods
return myFunc;
});

AMD講究的是前置執行。稍微複雜的例子以下,foo模塊有多個依賴及方法暴漏,瀏覽器

1
2
3
4
5
6
7
8
9
10
11
12
13
// filename: foo.js
define(['jquery', 'underscore'], function ($, _) {
// methods
function a(){}; // private because it's not returned (see below)
function b(){}; // public because it's returned
function c(){}; // public because it's returned

// exposed public methods
return {
b: b,
c: c
}
});

define是AMD規範用來聲明模塊的接口,示例中的第一個參數是一個數組,表示當前模塊的依賴。第二個參數是一個回調函數,表示此模塊的執行體。只有當依賴數組中的全部依賴模塊都是可用的時,AMD模塊加載器(好比RequireJS)纔會去執行回調函數並返回此模塊的暴露接口。babel

注意,回調函數中參數的順序與依賴數組中的依賴順序一致。(即:jquery->$underscore->_異步

固然,在這裏我能夠將回調函數的參數名稱改爲任何咱們想用的可用變量名,這並不會對模塊的聲明形成任何影響。

除此以外,你不能在模塊聲明的外部使用$或者_,由於他們只在模塊的回調函數體中才有定義。

關於AMD規定聲明模塊的更多內容,請參考這裏

CMD規範---經過require('加載依賴’)

CMD規範,全稱」Common Module Definition」,稱爲通用模塊加載規範。通常也是用在瀏覽器端。瀏覽器端異步加載庫Sea.js實現的就是CMD規範。

下面是使用AMD規範定義一個名爲foo模塊的方式,此模塊依賴jquery,

1
2
3
4
5
6
7
8
9
10
define(function (require, exports, module) {
// load dependence
var $ = require('jquery');

// methods
function myFunc(){};

// exposed public methods
return myFunc;
})

CMD規範傾向依賴就近,稍微複雜一點例子

1
2
3
4
5
6
7
8
9
10
11
12
define(function (requie, exports, module) {
// 依賴能夠就近書寫
var a = require('./a');
a.test();

// ...
// 軟依賴
if (status) {
var b = requie('./b');
b.test();
}
});

關於AMD和CMD的區別,可參考這篇文章,AMD/CMD與前端規範

CommonJS規範---require('加載模塊')--module.exports = 暴露的公共方法名稱

根據CommonJS規範,一個單獨的文件就是一個模塊。每個模塊都是一個單獨的做用域,也就是說,在一個文件定義的變量(還包括函數和類),都是私有的,對其餘文件是不可見的。

若是你在Node.js平臺上寫過東西,你應該會比較熟悉CommonJS規範。與前面的AMD及CMD規範不同的是,CommonJS規範通常應用於服務端(Node.js平臺),並且CommonJS加載模塊採用的是同步方式(這跟他適用的場景有關係)。同時,得力於Browserify這樣的第三方工具,咱們能夠在瀏覽器端使用採用CommonJS規範的js文件。

下面是使用CommonJS規範聲明一個名爲foo模塊的方式,同時依賴jquery模塊,

1
2
3
4
5
6
7
8
9
// filename: foo.js
// dependencies
var $ = require('jquery');

// methods
function myFunc(){};

// exposed public method (single)
module.exports = myFunc;

稍微複雜一點的示例以下,擁有多個依賴以及拋出多個接口,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// filename: foo.js
var $ = require('jquery');
var _ = require('underscore');

// methods
function a(){}; // private because it's omitted from module.exports (see below)
function b(){}; // public because it's defined in module.exports
function c(){}; // public because it's defined in module.exports

// exposed public methods
module.exports = {
b: b,
c: c
};

UMD規範--支持AMD和CommonJS規範

由於AMD,CommonJS規範是兩種不一致的規範,雖然他們應用的場景也不太一致,可是人們仍然是指望有一種統一的規範來支持這兩種規範。因而,UMD(Universal Module Definition,稱之爲通用模塊規範)規範誕生了。

客觀來講,這個UMD規範看起來的確沒有AMD和CommonJS規範簡約。可是它支持AMD和CommonJS規範,同時還支持古老的全局模塊模式。

咱們來看個示例,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS-like
module.exports = factory(require('jquery'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.jQuery);
}
}(this, function ($) {
// methods
function myFunc(){};

// exposed public method
return myFunc;
}));

我的以爲UMD規範更像一個語法糖。應用UMD規範的js文件其實就是一個當即執行函數。函數有兩個參數,第一個參數是當前運行時環境,第二個參數是模塊的定義體。在執行UMD規範時,會優先判斷是當前環境是否支持AMD環境,而後再檢驗是否支持CommonJS環境,不然認爲當前環境爲瀏覽器環境(window)。固然具體的判斷順序實際上是能夠調換的。

下面是一個更加複雜的示例,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery', 'underscore'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS-like
module.exports = factory(require('jquery'), require('underscore'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.jQuery, root._);
}
}(this, function ($, _) {
// methods
function a(){}; // private because it's not returned (see below)
function b(){}; // public because it's returned
function c(){}; // public because it's returned

// exposed public methods
return {
b: b,
c: c
}
}));

Tips: 若是你寫了一個小工具庫,你想讓它及支持AMD規範,又想讓他支持CommonJS規範,那麼採用UMD規範對你的代碼進行包裝吧,就像這樣

 

轉載自:http://blog.gejiawen.com/2015/11/03/what-is-amd-cmd-commonjs-umd/

感謝

相關文章
相關標籤/搜索