<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          JavaScript 模塊化的歷史進(jìn)程

          共 9062字,需瀏覽 19分鐘

           ·

          2020-07-27 18:25

          作者:然后去遠(yuǎn)足

          https://segmentfault.com/a/1190000023017398

          引言

          昨天在思否上閑逛,發(fā)現(xiàn)了一個(gè)有意思的問(wèn)題 。

          因?yàn)檫@個(gè)問(wèn)題,我產(chǎn)生了寫一個(gè)系列文章的想法,試圖從站在歷史的角度上來(lái)看待編程世界中林林總總的問(wèn)題和解決方案。

          目前中文網(wǎng)絡(luò)上充斥著大量互相“轉(zhuǎn)載”的內(nèi)容,基本是某一個(gè)技術(shù)問(wèn)題的解決方案(what??how?),卻不涉及為什么這么做和歷史緣由(why??when?)。比如你要搜 “JavaScript 有哪些模塊化方案?它們有什么區(qū)別?”,能得到一萬(wàn)個(gè)有用的結(jié)果;但要想知道 “為什么 JavaScript 有這么多模塊化方案?它們是誰(shuí)創(chuàng)建的?”,卻幾乎不可能。

          因此,這一系列文章內(nèi)會(huì)盡可能的不涉及具體代碼,只談歷史故事。但會(huì)在文末提供包含部分代碼的參考鏈接,以供感興趣的朋友自行閱讀。

          這個(gè)系列暫定為十篇文章,內(nèi)容會(huì)涉及前端、后端、編程語(yǔ)言、開(kāi)發(fā)工具、操作系統(tǒng)等等。也給自己立個(gè) Flag,在今年年底之前把整個(gè)系列寫完。如果沒(méi)完成目標(biāo)……就當(dāng)我沒(méi)說(shuō)過(guò)這句話(逃


          正文

          模塊化,是前端繞不過(guò)去的話題。

          隨著 Node.js 和三大框架的流行,越來(lái)越多的前端開(kāi)發(fā)者們腦海中都會(huì)時(shí)常浮現(xiàn)一個(gè)問(wèn)題:

          為什么 JavaScript 有這么多模塊化方案?

          自從 1995 年 5 月,Brendan Eich?寫下了第一行 JavaScript 代碼起,JavaScript 已經(jīng)誕生了 25 年。

          但這門語(yǔ)言早期僅僅作為輕量級(jí)的腳本語(yǔ)言,用于在 Web 上與用戶進(jìn)行少量的交互,并沒(méi)有依賴管理的概念。

          隨著 AJAX 技術(shù)得以廣泛使用,Web 2.0 時(shí)代迅猛發(fā)展,瀏覽器承載了愈來(lái)愈多的內(nèi)容與邏輯,JavaScript 代碼越來(lái)越復(fù)雜,全局變量沖突、依賴管理混亂等問(wèn)題始終縈繞在前端開(kāi)發(fā)者們的心頭。此時(shí),JavaScript 亟需一種在其他語(yǔ)言中早已得到良好應(yīng)用的功能 —— 模塊化。

          其實(shí),JavaScript 本身的標(biāo)準(zhǔn)化版本 ECMAScript 6.0 (ES6/ES2015) 中,已經(jīng)提供了模塊化方案,即?ES Module。但目前在 Node.js 體系下,最常見(jiàn)的方案其實(shí)是?CommonJS。再加上大家耳熟能詳?shù)?AMDCMDUMD,模塊化的事實(shí)標(biāo)準(zhǔn)如此之多。

          那么為什么有如此之多的模塊化方案?它們又是在怎樣的背景下誕生的?為什么沒(méi)有一個(gè)方案 “千秋萬(wàn)代,一統(tǒng)江湖”?

          接下來(lái),我會(huì)按照時(shí)間順序講述模塊化的發(fā)展歷程,順帶也就回答了上述幾個(gè)問(wèn)題。

          萌芽初現(xiàn):從 YUI Library 和 jQuery 說(shuō)起

          時(shí)間回到 2006 年 1 月,當(dāng)時(shí)還是國(guó)際互聯(lián)網(wǎng)巨頭的 Yahoo(雅虎),開(kāi)源了其內(nèi)部使用已久的組件庫(kù)?YUI Library

          YUI Library 采用了類似于 Java 命名空間的方式,來(lái)隔離各個(gè)模塊之間的變量,避免全局變量造成的沖突。其寫法類似于:

          YUI.util.module.doSomthing();

          這種寫法無(wú)論是封裝還是調(diào)用時(shí)都十分繁瑣,而且當(dāng)時(shí)的 IDE 對(duì)于 JavaScript 來(lái)說(shuō)智能感知非常弱,開(kāi)發(fā)者很難知道他需要的某個(gè)方法存在于哪個(gè)命名空間下,經(jīng)常需要頻繁地查閱開(kāi)發(fā)手冊(cè),導(dǎo)致開(kāi)發(fā)體驗(yàn)十分不友好。

          在 YUI 發(fā)布之后不久,John Resig?發(fā)布了?jQuery。當(dāng)時(shí)年僅 23 歲的他,不會(huì)知道自己這一時(shí)興起在 BarCamp 會(huì)議上寫下的代碼,將占據(jù)未來(lái)十幾年的 Web 領(lǐng)域。

          jQuery?使用了一種新的組織方式,它利用了 JavaScript 的 IIFE(立即執(zhí)行函數(shù)表達(dá)式)和閉包的特性,將所依賴的外部變量傳給一個(gè)包裝了自身代碼的匿名函數(shù),在函數(shù)內(nèi)部就可以使用這些依賴,最后在函數(shù)的結(jié)尾把自身暴露給?window。這種寫法被很多后來(lái)的框架所模仿,其寫法類似于:

          (function(root){
          // balabala
          root.jQuery = root.$ = jQuery;
          })(window);

          這種寫法雖然靈活性大大提升,可以很方便地添加擴(kuò)展,但它并未解決根本問(wèn)題:所需依賴還是得外部提前提供,還是會(huì)增加全局變量。

          從以上的嘗試中,可以歸納出 JavaScript 模塊化需要解決哪些問(wèn)題:

          1. 如何給模塊一個(gè)唯一標(biāo)識(shí)?

          2. 如何在模塊中使用依賴的外部模塊?

          3. 如何安全地(不污染模塊外代碼)包裝一個(gè)模塊?

          4. 如何優(yōu)雅地(不增加全局變量)把模塊暴漏出去?

          圍繞著這些問(wèn)題,JavaScript 模塊化開(kāi)始了一段曲折的探索之路。

          探索之路:CommonJS 與 Node.js 的誕生

          讓我們來(lái)到 2009 年 1 月,此時(shí)距離 ES6 發(fā)布尚有 5 年的時(shí)間,但前端領(lǐng)域已經(jīng)迫切地需要一套真正意義上的模塊化方案,以解決全局變量污染和依賴管理混亂等問(wèn)題。

          Mozilla 旗下的工程師?Kevin Dangoor,在工作之余,與同事們一起制訂了一套 JavaScript 模塊化的標(biāo)準(zhǔn)規(guī)范,并取名為?ServerJS

          ServerJS?最早用于服務(wù)端 JavaScript,旨在為配合自動(dòng)化測(cè)試等工作而提供模塊導(dǎo)入功能。

          這里插一句題外話,其實(shí)早期 1995 年,Netsacpe(網(wǎng)景)公司就提供了有在服務(wù)端執(zhí)行 JavaScript 能力的產(chǎn)品,名為?Netscape Enterprise Server。但此時(shí)服務(wù)端能做的 JavaScript 還是基于瀏覽器來(lái)實(shí)現(xiàn)的,本身沒(méi)有脫離其自帶的 API 范圍。直到 2009 年 5 月,Node.js?誕生,賦予了其文件系統(tǒng)、I/O 流、網(wǎng)絡(luò)通信等能力,才真正意義上的成為了一門服務(wù)端編程語(yǔ)言。

          2009 年年初,Ryan Dahl?產(chǎn)生了創(chuàng)造一個(gè)跨平臺(tái)編程框架的想法,想要基于 Google(谷歌)的?Chromium V8?引擎來(lái)實(shí)現(xiàn)。經(jīng)過(guò)幾個(gè)月緊張的開(kāi)發(fā)工作,在 5 月中旬,Node.js?首個(gè)預(yù)覽版本的開(kāi)發(fā)工作已全部結(jié)束。同年 8 月,歐洲 JSConf 開(kāi)發(fā)者大會(huì)上,Node.js?驚艷亮相。

          但在此刻,Node.js?還沒(méi)有一款包管理工具,外部依賴依然要手動(dòng)下載到項(xiàng)目目錄內(nèi)再引用。歐洲 JSConf 大會(huì)結(jié)束后,Isaac Z. Schlueter?注意到了?Node.js,兩人一拍即合,決定開(kāi)發(fā)一款包管理工具,也就是后來(lái)大名鼎鼎的?Node Package Manager(即?npm)。

          在開(kāi)發(fā)之初,擺在二人面前的第一個(gè)問(wèn)題就是,采用何種模塊化方案?。二人江目光鎖定在了幾個(gè)月前(2009 年 4 月)在華盛頓特區(qū)舉辦的美國(guó) JSConf 大會(huì)上公布的?ServerJS。此時(shí)的?ServerJS?已經(jīng)更名為?CommonJS,并重新制訂了標(biāo)準(zhǔn)規(guī)范,即Modules/1.0,展現(xiàn)了更大的野心,企圖一統(tǒng)所有編程語(yǔ)言的模塊化方案。

          具體來(lái)說(shuō),Modules/1.0標(biāo)準(zhǔn)規(guī)范包含以下內(nèi)容:

          1. 模塊的標(biāo)識(shí)應(yīng)遵循一定的書寫規(guī)則。

          2. 定義全局函數(shù)?require(dependency),通過(guò)傳入模塊標(biāo)識(shí)來(lái)引入其他依賴模塊,執(zhí)行的結(jié)果即為別的模塊暴漏出來(lái)的 API。

          3. 如果被?require?函數(shù)引入的模塊中也包含外部依賴,則依次加載這些依賴。

          4. 如果引入模塊失敗,那么?require?函數(shù)應(yīng)該拋出一個(gè)異常。

          5. 模塊通過(guò)變量?exports?來(lái)向外暴露 API,exports?只能是一個(gè)?object?對(duì)象,暴漏的 API 須作為該對(duì)象的屬性。

          由于這個(gè)規(guī)范簡(jiǎn)單而直接,Node.js?和?npm?很快就決定采用這種模塊化的方案。至此,第一個(gè) JavaScript 模塊化方案正式登上了歷史舞臺(tái),成為前端開(kāi)發(fā)中必不可少的一環(huán)。

          需要注意的是,CommonJS?是一系列標(biāo)準(zhǔn)規(guī)范的統(tǒng)稱,它包含了多個(gè)版本,從最早?ServerJS?時(shí)的?Modules/0.1,到更名為?CommonJS?后的?Modules/1.0,再到現(xiàn)在成為主流的?Modules/1.1。這些規(guī)范有很多具體的實(shí)現(xiàn),且不只局限于 JavaScript 這一種語(yǔ)言,只要遵循了這一規(guī)范,都可以稱之為?CommonJS。其中,Node.js?的實(shí)現(xiàn)叫做?Common Node ModulesCommonJS?的其他實(shí)現(xiàn),感興趣的朋友可以閱讀本文最下方的參考鏈接。

          值得一提的是,CommonJS?雖然沒(méi)有進(jìn)入 ECMAScript 標(biāo)準(zhǔn)范圍內(nèi),但?CommonJS?項(xiàng)目組的很多成員,也都是 TC39(即制訂 ECMAScript 標(biāo)準(zhǔn)的委員會(huì)組織)的成員。這也為日后 ES6 引入模塊化特性打下了堅(jiān)實(shí)的基礎(chǔ)。

          分道揚(yáng)鑣:CommonJS 歷史路口上的抉擇

          在推出?Modules/1.0?規(guī)范后,CommonJS?在?Node.js?等環(huán)境下取得了很不錯(cuò)的實(shí)踐。

          但此時(shí)的?CommonJS?有兩個(gè)重要問(wèn)題沒(méi)能得到解決,所以遲遲不能推廣到瀏覽器上:

          1. 由于外層沒(méi)有?function?包裹,被導(dǎo)出的變量會(huì)暴露在全局中。

          2. 在服務(wù)端?require?一個(gè)模塊,只會(huì)有磁盤 I/O,所以同步加載機(jī)制沒(méi)什么問(wèn)題;但如果是瀏覽器加載,一是會(huì)產(chǎn)生開(kāi)銷更大的網(wǎng)絡(luò) I/O,二是天然異步,就會(huì)產(chǎn)生時(shí)序上的錯(cuò)誤。

          因此,社區(qū)意識(shí)到,要想在瀏覽器環(huán)境中也能順利使用?CommonJS,勢(shì)必重新制訂新的標(biāo)準(zhǔn)規(guī)范。但新的規(guī)范怎么制訂,成為了激烈爭(zhēng)論的焦點(diǎn),分歧和沖突由此誕生,逐步形成了三大流派:

          • Modules/1.x?派:這派的觀點(diǎn)是,既然?Modules/1.0?已經(jīng)在服務(wù)器端有了很好的實(shí)踐經(jīng)驗(yàn),那么只需要將它移植到瀏覽器端就好。在瀏覽器加載模塊之前,先通過(guò)工具將模塊轉(zhuǎn)換成瀏覽器能運(yùn)行的代碼了。我們可以理解為他們是“保守派”。

          • Modules/Async?派:這派認(rèn)為,既然瀏覽器環(huán)境于服務(wù)器環(huán)境差異過(guò)大,那么就不應(yīng)該繼續(xù)在?Modules/1.0?的基礎(chǔ)上小修小補(bǔ),應(yīng)該遵循瀏覽器本身的特點(diǎn),放棄?require?方式改為回調(diào),將同步加載模塊變?yōu)楫惒郊虞d模塊,這樣就可以通過(guò) ”下載 -> 回調(diào)“ 的方式,避免時(shí)序問(wèn)題。我們可以理解為他們是“激進(jìn)派”。

          • Modules/2.0?派:這派同樣也認(rèn)為不應(yīng)該沿用?Modules/1.0,但也不向激進(jìn)派一樣過(guò)于激進(jìn),認(rèn)為?require?等規(guī)范還是有可取之處,不應(yīng)該隨隨便便放棄,而是要盡可能的保持一致;但激進(jìn)派的優(yōu)點(diǎn)也應(yīng)該吸收,比如?exports?也可以導(dǎo)出其他類型、而不僅局限于?object?對(duì)象。我們可以理解為他們是“中間派”。

          其中保守派的思路跟今天通過(guò)?babel?等工具,將 JavaScript 高版本代碼轉(zhuǎn)譯為低版本代碼如出一轍,主要目的就是為了兼容。有了這種想法,這派人馬提出了?Modules/Transport?規(guī)范,用于規(guī)定模塊如何轉(zhuǎn)譯。browserify?就是這一觀點(diǎn)下的產(chǎn)物。

          激進(jìn)派也提出了自己的規(guī)范?Modules/AsynchronousDefinition,奈何這一派的觀點(diǎn)并沒(méi)有得到?CommonJS?社區(qū)的主流認(rèn)可。

          中間派同樣也有自己的規(guī)范?Modules/Wrappings,但這派人馬最后也不了了之,沒(méi)能掀起什么風(fēng)浪。

          激進(jìn)派、中間派與保守派的理念不和,最終為?CommonJS?社區(qū)分裂埋下伏筆。

          百家爭(zhēng)鳴:激進(jìn)派 —— AMD 的崛起

          激進(jìn)派的?James Burke?在 2009 年 9 月開(kāi)發(fā)出了?RequireJS?這一模塊加載器,以實(shí)踐證明自己的觀點(diǎn)。

          但激進(jìn)派的想法始終得不到?CommonJS?社區(qū)主流認(rèn)可。雙方的分歧點(diǎn)主要在于執(zhí)行時(shí)機(jī)問(wèn)題,Modules/1.0?是延遲加載、且同一模塊只執(zhí)行一次,而?Modules/AsynchronousDefinition?卻是提前加載,加之破壞了就近聲明(就近依賴)原則,還引入了?define?等新的全局函數(shù),雙方的分歧越來(lái)越大。

          最終,在?James BurkeKarl Westin?等人的帶領(lǐng)下,激進(jìn)派于同年年底宣布離開(kāi)?CommonJS?社區(qū),自立門戶。

          激進(jìn)派在離開(kāi)社區(qū)后,起初專注于?RequireJS?的開(kāi)發(fā)工作,并沒(méi)有過(guò)多的涉足社區(qū)工作,也沒(méi)有此草新的標(biāo)準(zhǔn)規(guī)范。

          2011 年 2 月,在?RequireJS?的擁躉們的共同努力下,由?Kris Zyp?起草的?Async Module Definition(簡(jiǎn)稱?AMD)標(biāo)準(zhǔn)規(guī)范正式發(fā)布,并在?RequireJS?社區(qū)的基礎(chǔ)上建立了?AMD?社區(qū)。

          AMD?標(biāo)準(zhǔn)規(guī)范主要包含了以下幾個(gè)內(nèi)容:

          1. 模塊的標(biāo)識(shí)遵循?CommonJS Module Identifiers

          2. 定義全局函數(shù)?define(id, dependencies, factory),用于定義模塊。dependencies?為依賴的模塊數(shù)組,在?factory?中需傳入形參與之一一對(duì)應(yīng)。

          3. 如果?dependencies?的值中有?requireexports?或module,則與?CommonJS?中的實(shí)現(xiàn)保持一致。

          4. 如果?dependencies?省略不寫,則默認(rèn)為?['require', 'exports', 'module']factory?中也會(huì)默認(rèn)傳入三者。

          5. 如果?factory?為函數(shù),模塊可以通過(guò)以下三種方式對(duì)外暴漏 API:return?任意類型;exports.XModule = XModulemodule.exports = XModule

          6. 如果?factory?為對(duì)象,則該對(duì)象即為模塊的導(dǎo)出值。

          其中第三、四兩點(diǎn),即所謂的?Modules/Wrappings,是因?yàn)?AMD?社區(qū)對(duì)于要寫一堆回調(diào)這種做法頗有微辭,最后?RequireJS?團(tuán)隊(duì)妥協(xié),搞出這么個(gè)部分兼容支持。

          因?yàn)?AMD?符合在瀏覽器端開(kāi)發(fā)的習(xí)慣方式,也是第一個(gè)支持瀏覽器端的 JavaScript 模塊化解決方案,RequireJS?迅速被廣大開(kāi)發(fā)者所接受。

          但有?CommonJS?珠玉在前,很多開(kāi)發(fā)者對(duì)于要寫很多回調(diào)的方式頗有微詞。在呼吁高漲聲中,RequireJS?團(tuán)隊(duì)最終妥協(xié),搞出個(gè)?Simplified CommonJS wrapping(簡(jiǎn)稱?CJS)的兼容方式,即上文的第三、四兩點(diǎn)。但由于背后實(shí)際還是?AMD,所以只是寫法上做了兼容,實(shí)際上并沒(méi)有真正做到?CommonJS?的延遲加載。

          與?CommonJS?規(guī)范有眾多實(shí)現(xiàn)不同的是,AMD?只專注于 JavaScript 語(yǔ)言,且實(shí)現(xiàn)并不多,目前只有?RequireJS?和?Dojo Toolkit,其中后者已經(jīng)停止維護(hù)。

          一波三折:中間派 —— CMD 的衰落

          由于?AMD?的提前加載的問(wèn)題,被很多開(kāi)發(fā)者擔(dān)心會(huì)有性能問(wèn)題而吐槽。

          例如,如果一個(gè)模塊依賴了十個(gè)其他模塊,那么在本模塊的代碼執(zhí)行之前,要先把其他十個(gè)模塊的代碼都執(zhí)行一遍,不管這些模塊是不是馬上會(huì)被用到。這個(gè)性能消耗是不容忽視的。

          為了避免這個(gè)問(wèn)題,上文提到,中間派試圖保留?CommonJS?書寫方式和延遲加載、就近聲明(就近依賴)等特性,并引入異步加載機(jī)制,以適配瀏覽器特性。

          其中一位中間派的大佬?Wes Garland,本身是?CommonJS?的主要貢獻(xiàn)者之一,在社區(qū)中很受尊重。他在?CommonJS?的基礎(chǔ)之上,起草了?Modules/2.0,并給出了一個(gè)名為?BravoJS?的實(shí)現(xiàn)。

          另一位中間派大佬?@khs4473?提出了?Modules/Wrappings,并給出了一個(gè)名為?FlyScript?的實(shí)現(xiàn)。

          但?Wes Garland?本人是學(xué)院派,理論功底十分扎實(shí),但寫出的作品卻既不優(yōu)雅也不實(shí)用。而實(shí)戰(zhàn)派的?@khs4473?則在與?James Burke?發(fā)生了一些爭(zhēng)論,最后刪除了自己的 GitHub 倉(cāng)庫(kù)并停掉了?FlyScript?官網(wǎng)。

          到此為止,中間一派基本已全軍覆滅,空有理論,沒(méi)有實(shí)踐。

          讓我們前進(jìn)到 2011 年 4 月,國(guó)內(nèi)阿里巴巴集團(tuán)的前端大佬玉伯(本名王保平),在給?RequireJS?不斷提出建議卻被拒絕之后,萌生了自己寫一個(gè)模塊加載器的想法。

          在借鑒了?CommonJSAMD?等模塊化方案后,玉伯寫出了?SeaJS,不過(guò)這一實(shí)現(xiàn)并沒(méi)有嚴(yán)格遵守?Modules/Wrappings?的規(guī)范,所以嚴(yán)格來(lái)說(shuō)并不能稱之為?Modules/2.0。在此基礎(chǔ)上,玉伯提出了?Common Module Definition(簡(jiǎn)稱?CMD)這一標(biāo)準(zhǔn)規(guī)范。

          CMD?規(guī)范的主要內(nèi)容與?AMD?大致相同,不過(guò)保留了?CommonJS?中最重要的延遲加載、就近聲明(就近依賴)特性。

          隨著國(guó)內(nèi)互聯(lián)網(wǎng)公司之間的技術(shù)交流,SeaJS?在國(guó)內(nèi)得到了廣泛使用。不過(guò)在國(guó)外,也許是因?yàn)檎Z(yǔ)言障礙等原因,并沒(méi)有得到非常大范圍的推廣。

          兼容并濟(jì):UMD 的統(tǒng)一

          2014 年 9 月,美籍華裔?Homa Wong?提交了?UMD?第一個(gè)版本的代碼。

          UMD?即?Universal Module Definition?的縮寫,它本質(zhì)上并不是一個(gè)真正的模塊化方案,而是將?CommonJS?和?AMD?相結(jié)合。

          UMD?作出了如下內(nèi)容的規(guī)定:

          1. 優(yōu)先判斷是否存在?exports?方法,如果存在,則采用?CommonJS?方式加載模塊;

          2. 其次判斷是否存在?define?方法,如果存在,則采用?AMD?方式加載模塊;

          3. 最后判斷?global?對(duì)象上是否定義了所需依賴,如果存在,則直接使用;反之,則拋出異常。

          這樣一來(lái),模塊開(kāi)發(fā)者就可以使自己的模塊同時(shí)支持?CommonJS?和?AMD?的導(dǎo)出方式,而模塊使用者也無(wú)需關(guān)注自己依賴的模塊使用的是哪種方案。

          姍姍來(lái)遲:欽定的 ES6/ES2015

          時(shí)間前進(jìn)到 2016 年 5 月,經(jīng)過(guò)了兩年的討論,ECMAScript 6.0 終于正式通過(guò)決議,成為了國(guó)際標(biāo)準(zhǔn)。

          在這一標(biāo)準(zhǔn)中,首次引入了?import?和?export?兩個(gè) JavaScript 關(guān)鍵字,并提供了被稱為?ES Module?的模塊化方案。

          在 JavaScript 出生的第 21 個(gè)年頭里,JavaScript 終于迎來(lái)了屬于自己的模塊化方案。

          但由于歷史上的先行者已經(jīng)占據(jù)了優(yōu)勢(shì)地位,所以?ES Module?遲遲沒(méi)有完全替換上文提到的幾種方案,甚至連瀏覽器本身都沒(méi)有立即作出支持。

          2017 年 9 月上旬,Chrome?61.0 版本發(fā)布,首次在瀏覽器端原生支持了?ES Module

          2017 年 9 月中旬,Node.js?迅速跟隨,發(fā)布了 8.5.0,以支持原生模塊化,這一特性被稱之為?ECMAScript Modules(簡(jiǎn)稱?MJS)。不過(guò)到目前為止,這一特性還處于試驗(yàn)性階段。

          不過(guò)隨著?babelWebpackTypeScript?等工具的興起,前端開(kāi)發(fā)者們已經(jīng)不再關(guān)心以上幾種方式的兼容問(wèn)題,習(xí)慣寫哪種就寫哪種,最后由工具統(tǒng)一轉(zhuǎn)譯成瀏覽器所支持的方式。

          因此,預(yù)計(jì)在今后很長(zhǎng)的一段時(shí)間里,幾種模塊化方案都會(huì)在前端開(kāi)發(fā)中共存。


          尾聲

          本文以時(shí)間線為基準(zhǔn),從作者、社區(qū)、理念等幾個(gè)維度談到了 JavaScript 模塊化的幾大方案。

          其實(shí)模塊化方案遠(yuǎn)不止提到的這些,但其他的都沒(méi)有這些流行,這里也就不費(fèi)筆墨。

          文中并沒(méi)有提及各個(gè)模塊化方案是如何實(shí)現(xiàn)的,也沒(méi)有給出相關(guān)的代碼示例,感興趣的朋友可以自行閱讀下方的參考閱讀鏈接。

          下面我們?cè)倏偨Y(jié)梳理一下時(shí)間線:

          時(shí)間事件
          1995.05? ? ??Brendan Eich?開(kāi)發(fā) JavaScript。
          2006.01Yahoo 開(kāi)源?YUI Library,采用命名空間方式管理模塊。
          2006.01John Resig?開(kāi)發(fā)?jQuery,采用 IIFE + 閉包管理模塊。
          2009.01Kevin Dangoor?起草?ServerJS,并公布第一個(gè)版本?Modules/0.1
          2009.04Kevin Dangoor?在美國(guó) JSConf 公布?CommonJS
          2009.05Ryan Dahl?開(kāi)發(fā)?Node.js
          2009.08Ryan Dahl?在歐洲 JSConf 公布?Node.js
          2009.08Kevin Dangoor?將?ServerJS?改名為?CommonJS,并起草第二個(gè)版本?Modules/1.0
          2009.09James Burke?開(kāi)發(fā)?RequireJS
          2010.01Isaac Z. Schlueter?開(kāi)發(fā)?npm,實(shí)現(xiàn)了基于?CommonJS?模塊化方案的?Common Node Modules
          2010.02Kris Zyp?起草?AMDAMD/RequireJS?社區(qū)成立。
          2011.01玉伯開(kāi)發(fā)?SeaJS,起草?CMDCMD/SeaJS?社區(qū)成立。
          2014.08Homa Wong?開(kāi)發(fā)?UMD
          2015.05ES6 發(fā)布,新增特性?ES Module
          2017.09Chrome?和?Node.js?開(kāi)始原生支持?ES Module

          注:文章中的所有人物、事件、時(shí)間、地點(diǎn),均來(lái)自于互聯(lián)網(wǎng)公開(kāi)內(nèi)容,由本人進(jìn)行搜集整理,其中如有謬誤之處,還請(qǐng)多多指教。


          參考閱讀

          • 《Wikipedia - YUI Library》

          • 《Wikipedia - jQuery》

          • 《Wikipedia - List of server-side JavaScript implementations》

          • 《Wikipedia - CommonJS》

          • 《Wikipedia - Asynchronous Module Definition》

          • 《CommonJS Project History》

          • 《RequireJS Project History》

          • 《JavaScript Modules: A Brief History》

          • 《淺析 JS 模塊規(guī)范:AMD,CMD,CommonJS》

          • 《JavaScript Module Loader - CommonJS,RequireJS,SeaJS 歸納筆記》

          • 《前端模塊化開(kāi)發(fā)那點(diǎn)歷史》

          分享前端好文,點(diǎn)亮?在看?

          瀏覽 92
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品五月天久久久 | AV网站免费在线观看 | 一区二区三区亚洲动漫 | 丁香五月激情在线 | 国产亚洲女午夜秀场 |