如果您覺得該文檔對您有幫助,請打賞,五毛十毛均可。另外,轉(zhuǎn)載請注明作者及出處。
Web 應(yīng)用程序已經(jīng)變得非常復(fù)雜,我們需要用項目構(gòu)建工具來應(yīng)對這種復(fù)雜性,處理各種可能遇到的問題
模塊系統(tǒng)的標(biāo)準(zhǔn)問題
目前模塊系統(tǒng)有幾種不同的標(biāo)準(zhǔn):
-
<script>
標(biāo)簽 (沒有模塊系統(tǒng)) CommonJS
AMD
-
ES6
模塊 - 其他
<script>
標(biāo)簽
使用 <script>
標(biāo)簽,可以在沒有模塊系的情況下,對代碼進(jìn)行簡單的管理,之前我們都是這樣做的:
<script src="module1.js"></script>
<script src="module2.js"></script>
<script src="libraryA.js"></script>
<script src="module3.js"></script>
各個模塊中的接口都會被導(dǎo)入到全局對象中,比如 window
對象;這樣就可以在任何地方通過全局對象訪問這些接口
問題:
- 可會能引發(fā)沖突
- 加載順序難以管理
- 依賴問題難以管理
- 引入的腳本會非常多,難以閱讀和理解
CommonJs 標(biāo)準(zhǔn):同步 require
創(chuàng)建模塊的時候,通過給 exports
對象添加屬性和方法,或者通過給 module.exports
設(shè)置值來定義模塊的接口。
引用的時候,使用同步 require
方法導(dǎo)入模塊的接口。
//導(dǎo)入模塊
require("module");
require("../file.js");
//創(chuàng)建模塊接口
exports.doStuff = function() {};
module.exports = someValue;
這種方法常常被用在服務(wù)端的 node.js
程序中。
優(yōu)點
- 在服務(wù)端,模塊可以被重用
- 已經(jīng)有大量這樣的模塊,通過
npm
管理 - 簡單
缺點
- 因為是同步導(dǎo)入模塊,會導(dǎo)致程序掛起,不適用于網(wǎng)絡(luò)應(yīng)用
- 不能并行導(dǎo)入多個模塊
實現(xiàn)
-
node.js
用在服務(wù)端 browserify
-
modules-webmake
編譯成一個包 -
wreq
用在客戶端
AMD 標(biāo)準(zhǔn):異步 require
AMD 標(biāo)準(zhǔn)中,定義模塊和導(dǎo)入模塊的方式與 CommonJs 是不一樣的
//導(dǎo)入模塊
require(["module", "../file"], function(module, file) { /* ... */ });
//定義模塊
define("mymodule", ["dep1", "dep2"], function(d1, d2) {
return someExportedValue;
});
優(yōu)點:
- 適用于網(wǎng)絡(luò)應(yīng)用
- 可以并行導(dǎo)入多個模塊
缺點:
- 編碼復(fù)雜,閱讀和書寫都很困難
- 有很多替代方法
實現(xiàn):
-
require.js
客戶端 -
curl
客戶端
ES6 模塊
EcmaScript6 從語言層面內(nèi)建了模塊系統(tǒng)
import "jquery";
export function doStuff() {}
module "localModule" {}
優(yōu)點:
- 行業(yè)標(biāo)準(zhǔn)
確定:
- 目前很多瀏覽器還不支持 ES6
- 目前很少有模塊使用這種方式
最佳方式
能夠讓開發(fā)者自己選擇模塊標(biāo)準(zhǔn),即時可以使用已經(jīng)存在的代碼庫,也能容易的添加自己定義的模塊。
傳輸問題
如果想讓模塊在客戶端執(zhí)行,必須通過網(wǎng)絡(luò)從服務(wù)端將他們傳輸過來。極端情況下,會出現(xiàn)下面這兩種情況:
- 為每個模塊發(fā)送一個請求
- 所有模塊只用一個請求
通常,我們兩種情況都會遇到,兩種情況都存在一些問題:
-
每個模塊一個請求
- 優(yōu)點:只請求需要的模塊
- 缺點:會有很多請求,造成性能問題
-
所有模塊一個請求
- 優(yōu)點:請求少,不會造成性能問題
- 確定:會引入很多無用的模塊
折中方式
折中的方式是:將所有模塊編譯成幾個小的分塊,減少了請求數(shù)量,也減少了無效的引用
資源管理問題
當(dāng)前的 Web 引用已經(jīng)很復(fù)雜,除了 Javascript
,還有其他各種資源需要引入:
-
stylesheets
樣式表 -
images
圖片 -
webfonts
字體 -
html
模板 - 其他
除此以外,還有一些翻譯轉(zhuǎn)換工作
-
coffeescript
→javascript
-
elm
→javascript
-
less stylesheets
→css stylesheets
-
jade templates
→javascript which - generates html
-
i18n files
→something
- 其他
我們希望能像下面這樣引入資源
require("./style.css");
require("./style.less");
require("./template.jade");
require("./image.png");
依賴管理問題
現(xiàn)代 Web 應(yīng)用會導(dǎo)入很多外部依賴,管理起來非常困難,特別是某些依賴還是以表達(dá)式的形式出現(xiàn),比如
require("./template/" + templateName + ".jade")
除此以外,還有很多其他稀奇古怪的形式。
策略
一個優(yōu)秀的解析器可以讓使用各種古怪依賴管理的代碼正常運行。