這篇博文介紹了兩個未來發展的趨勢(HTTP/2 和原生模組)對模組打包產生了何種影響。
1. 為什麼要用模組打包
繫結打包指的是把幾個帶有模組的檔案組合到一起,成為一個單一檔案。這麼做有三個理由:
- 在載入所有的模組時,需要檢索的檔案數量可以降低。
- 壓縮一個打包檔案要比壓縮多個單獨的檔案更有效率一些。
- 沒用使用的 exports 會在打包過程中被移除,這樣能極大程度地節省記憶體空間。
2. JavaScript 模組
隨著 ECMAScript 6 的提出, JavaScript 終於支援內建的模組功能了。(在本文餘下內容中,我都將用 JavaScript 模組指代它)儘管如此, JavaScript 的模組化現在還處於一個有點兒尷尬的位置:
一方面, ES6 對模組化進行了語法和語義的標準化。 ES6 制定的規則成為了比較流行的模組書寫格式,它的靜態結構能自動省略沒使用的 exports (JavaScript 中也稱這種技術為 “tree-shaking”)
而另一方面,關於如何載入 JavaScript 模組的標準化程式仍在制定過程中,並且截至目前也還沒有原生的 JavaScript 引擎支援它們。也就是說,目前唯一使用JavaScript模組的方式是將其編譯為一種非原生的格式,比較流行的解決方案有:browserify, webpack, jspm和Rollup。
3. 模組打包的未來發展趨勢。
接下來,我們一起看看未來將有很大發展空間的兩個潛力股,以及它們對 JavaScript 模組打包的影響。
3.1 潛力股一號種子選手: HTTP/2
HTTP/2 正有條不紊地發展壯大。在上文列舉的三個使用模組打包的理由當中,HTTP/2 主要影響其中第一條理由:HTTP/2 跟 HTTP/1相比 ,能極大程度地降低每個網頁請求的代價,也就是說下載單個檔案和下載多個檔案相比,並不能顯著地提升效能。既然如此,那我們可以使用更小型的、增量式更新方法。使用打包的話,就不得不下載整個打包後的檔案。而不用打包的話,我們可以只下載內容發生改變的那部分(而其它部分的檔案仍儲存在瀏覽器快取中)。
但是 HTTP/2 並不影響使用模組打包的第二和第三個原因。所以以後我們可能會使用混合式的方法,既有利於增量式更新,又能減少下載內容的大小。
3.2 潛力股二號種子選手: 原生 JavaScript 模組
一旦引擎支援原生的 JavaScript 模組的話,這是否會給打包帶來影響呢?就連原生執行在瀏覽器上的 AMD 模組,它都有一套定製化的繫結格式(和自己的小型載入器)。那麼原生的 JavaScript 模組比 AMD 模組有什麼過人之處嗎?答案應該是肯定的。Rollup 支援將多個 JS 模組打包成一個 JS 模組。
1 2 3 4 5 6 7 |
// lib.js export function foo() {} export function bar() {} // main.js import {foo} from './lib.js'; console.log(foo()); |
以下面兩個 JS 模組為例:
1 2 3 4 5 6 7 |
// lib.js export function foo() {} export function bar() {} // main.js import {foo} from './lib.js'; console.log(foo()); |
Rollup 能將這兩個 JS 模組繫結成下面的一個 JS 模組 (注意未使用的 export bar 被刪除了):
1 2 3 |
function foo() {} console.log(foo()); |
創始人 Rich Harris 坦言,起初,沒人想到JavaScript模組會引入打包機制。
當初我研究 Rollup 的時候,連我自己都沒想到它能成功。
JS模組處理 imports的方式有助於打包: imports 不是 exports 的複製變數, 只能對 imports 執行只讀操作。
在Rollup 官網上,你可以體驗一下它的功能。
4. 延伸閱讀
- “Building for HTTP/2” 作者 Rebecca Murphey (主要介紹了在新版 HTTP 中的最佳實踐發生的徹底改變)
- Chap. “Modules” in “Exploring ES6” (主要介紹了 ES6 modules 的工作機制)
- “Babel and CommonJS modules” (介紹瞭如何通過 Babel 實現 交叉編譯的 ES6 模組與 CommonJS 模組互通)
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!
任選一種支付方式