RequireJS 歷史
我在 Dojo Loader 上投入許多心力。一般的 dojo loader 過去使用同步的 XMLHttpRequest (XHR) 呼叫。然而,XHR loader 無法從其他網域載入 Dojo 模組,因為有同源限制。因此我建立了 xdomain loader,需要一個建置步驟來注入函式包裝器,類似 RequireJS 使用的方式,但更複雜,因為有 i18n 捆綁載入和 dojo.requireIf 行為。由於有更複雜的 i18n 和 requireIf 需求,以及世界上已經有許多 dojo 模組,我認為 Dojo 社群不會考慮手動撰寫有函式包裝器的模組。
然而,同步 XHR 載入器還有其他問題,例如讓除錯變得更困難。在 2009 年,David Mark 建議 Dojo 使用 document.write() 在頁面載入前載入模組以協助解決此問題,但這表示所需的相依項會在目前模組執行後才會載入。如果模組將相依項作為模組定義的一部分來參照,這可能會導致錯誤。因此需要一個函式包裝器。Dojo 社群似乎比較願意考慮函式包裝器,特別是因為我們正在考慮可以中斷一些 API 的 Dojo 2.0。我在 dojo-contributors 清單中詳細說明了 RequireJS(當時稱為 RunJS)的一些細節,而 Mike Wilson 最初推動一個更通用的載入器,它可以載入純文字檔以及允許不同的內容。
YUI 3 的 use() 函式也與 require 非常類似,而 use() 的 API(但不是程式碼)也告知了 RequireJS 的結構。我相信 RequireJS 更為通用,因為 YUI 似乎為其模組使用標籤,而這些標籤並未直接對應到檔案路徑。我也喜歡將相依模組明確地傳遞為函式定義的引數,因為它允許像 JSLint 這樣的程式碼檢查工具更有效。
我原本想要一些可以與 CommonJS 模組搭配運作的東西,但這些模組似乎是假設一個同步模組載入器,這在伺服器端 JavaScript 環境中是可能的。然而,我主要關注的是在瀏覽器中運作良好的東西,這表示需要一個函式包裝器,這樣我們才能使用腳本標籤。對於新手開發人員或希望跨瀏覽器輕鬆除錯的人來說,使用同步 XHR 並不友善。它也可能比純文字檔標籤載入慢。像 Adobe AIR 這樣的某些環境不允許 eval(),而且大多數開發人員都被教導 eval() 是邪惡的,應該避免使用。
我以 RunJS 建立了 RequireJS 的種子。當我試圖與 CommonJS 模組更同步以允許更多程式碼重複使用時,我提出了 CommonJS Transport/C 提案。傳輸格式允許將傳統的 CommonJS 模組對應到在瀏覽器中運作最好的格式。然後我將 RunJS 程式碼轉換為 RequireJS 以符合 Transport/C 提案中的 API。
在實作傳輸格式的過程中,越來越明顯的是,CommonJS 模組允許使用命令式的 require(),這在網路上很尷尬。許多情況在網路內容中無法運作,而更好的解決方案是允許在這些情況下使用基於回呼的 require。然而,CommonJS 清單上的一些參與者希望即使在回呼式 require 中也保留命令式使用,這使得該 API 比應有的更冗長。
Transport/C 提案進行了一些調整,而 Kris Zyp 找出如何在該格式中讓匿名模組運作。在那個時候,Kris 覺得它可以作為模組 API 提案,而不仅仅是傳輸格式,他在 CommonJS wiki 上為非同步模組定義 (AMD) API 建立了一個提案。在討論該 API 期間,Tom Robinson 建議使用 Function.prototype.toString() 來掃描工廠函式以尋找相依項,儘管 Tom 通常不喜歡 AMD API。toString() 掃描被納入 AMD API 中作為簡化的 CommonJS 封裝,因為並非所有 JS 環境都支援可用的 toString() 值。
CommonJS 清單上的一些參與者認為 AMD API 提案不符合 CommonJS 模組的原始目標,因為它未在 CommonJS 模組中保留完整的命令式 require() 樣式。他們也認為該提案在清單上突然出現,並以不當的方式實作和宣傳,儘管從我的角度來看,它被標記為提案,而且還有其他人討論他們對其他 CommonJS 提案的實作。
溝通中斷的情況相當嚴重,導致難以在 CommonJS 清單上繼續討論 AMD。然而,我們這些網路開發人員中仍有許多人認為它有價值,而且在載入器外掛程式和回呼要求方面仍有一些 API 工作要做,因此成立了 amd-implement 電子郵件清單和 amdjs Github 群組,以繼續進行這些討論。
透過 amd-implement 清單,回呼要求和載入器外掛程式 API 獲得了更多的定義和一組單元測試。製作了更多 AMD 實作。Dojo 已經開始進行程式碼轉換流程以使用 AMD,而 MooTools 和 EmbedJS 等其他人也採用了它。AMD 載入器在 jQuery 社群中獲得了支持,特別是在那些想要模組化 JS 載入功能的人之間。
AMD 現在擁有健康的生態系統。我持續提供 RequireJS 中的穩固實作來協助推動 AMD 的進展,並確保它能與網路良好配合。