這次是前端精讀期刊與大家第一次正式碰面,我們每周會(huì)精讀并分析若干篇精品好文,試圖討論出結(jié)論性觀點(diǎn)。愛(ài)掏網(wǎng) - it200.com沒(méi)錯(cuò),我們?cè)噲D通過(guò)觀點(diǎn)的碰撞,爭(zhēng)做無(wú)主觀精品好文的意見領(lǐng)袖。愛(ài)掏網(wǎng) - it200.com
我是這一期的主持人 —— 黃子毅
本期精讀的文章是:evolutionOfJsModularity。愛(ài)掏網(wǎng) - it200.com
懶得看文章?沒(méi)關(guān)系,稍后會(huì)附上文章內(nèi)容概述,同時(shí),更希望能通過(guò)閱讀這一期的精讀,穿插著深入閱讀原文。愛(ài)掏網(wǎng) - it200.com
1 引言
https://github.com/dt-fe/weekly/raw/master/assets/1/cube.jpeg
如今,Javascript 模塊化規(guī)范非常方便、自然,但這個(gè)新規(guī)范僅執(zhí)行了2年,就在 4 年前,js 的模塊化還停留在運(yùn)行時(shí)支持,10 年前,通過(guò)后端模版定義、注釋定義模塊依賴。愛(ài)掏網(wǎng) - it200.com對(duì)經(jīng)歷過(guò)來(lái)的人來(lái)說(shuō),歷史的模塊化方式還停留在腦海中,反而新上手的同學(xué)會(huì)更快接受現(xiàn)代的模塊化規(guī)范。愛(ài)掏網(wǎng) - it200.com
但為什么要了解 Javascript 模塊化發(fā)展的歷史呢?因?yàn)榉彩露加袃擅嫘裕私?Javascript 模塊化規(guī)范,有利于我們思考出更好的模塊化方案,縱觀歷史,從 1999 年開始,模塊化方案最多維持兩年,就出現(xiàn)了新的替代方案,比原有的模塊化更清晰、強(qiáng)壯,我們不能被現(xiàn)代模塊化方式限制住思維,因?yàn)楝F(xiàn)在的 ES2024 模塊化方案距離發(fā)布也僅僅過(guò)了兩年。愛(ài)掏網(wǎng) - it200.com
2 內(nèi)容概要
直接定義依賴 (1999): 由于當(dāng)時(shí) js 文件非常簡(jiǎn)單,模塊化方式非常簡(jiǎn)單粗暴 —— 通過(guò)全局方法定義、引用模塊。愛(ài)掏網(wǎng) - it200.com這種定義方式與現(xiàn)在的 commonjs 非常神似,區(qū)別是 commonjs 以文件作為模塊,而這種方法可以在任何文件中定義模塊,模塊不與文件關(guān)聯(lián)。愛(ài)掏網(wǎng) - it200.com
閉包模塊化模式 (2003): 用閉包方式解決了變量污染問(wèn)題,閉包內(nèi)返回模塊對(duì)象,只需對(duì)外暴露一個(gè)全局變量。愛(ài)掏網(wǎng) - it200.com
模版依賴定義 (2006): 這時(shí)候開始流行后端模版語(yǔ)法,通過(guò)后端語(yǔ)法聚合 js 文件,從而實(shí)現(xiàn)依賴加載,說(shuō)實(shí)話,現(xiàn)在 go 語(yǔ)言等模版語(yǔ)法也很流行這種方式,寫后端代碼的時(shí)候不覺(jué)得,回頭看看,還是掛在可維護(hù)性上。愛(ài)掏網(wǎng) - it200.com
注釋依賴定義 (2006): 幾乎和模版依賴定義同時(shí)出現(xiàn),與 1999 年方案不同的,不僅僅是模塊定義方式,而是終于以文件為單位定義模塊了,通過(guò) lazyjs 加載文件,同時(shí)讀取文件注釋,繼續(xù)遞歸加載剩下的文件。愛(ài)掏網(wǎng) - it200.com
外部依賴定義 (2007): 這種定義方式在 cocos2d-js 開發(fā)中普遍使用,其核心思想是將依賴抽出單獨(dú)文件定義,這種方式不利于項(xiàng)目管理,畢竟依賴抽到代碼之外,我是不是得兩頭找呢?所以才有通過(guò) webpack 打包為一個(gè)文件的方式暴力替換為 commonjs 的方式出現(xiàn)。愛(ài)掏網(wǎng) - it200.com
Sandbox模式 (2009): 這種模塊化方式很簡(jiǎn)單,暴力,將所有模塊塞到一個(gè) sanbox
變量中,硬傷是無(wú)法解決明明沖突問(wèn)題,畢竟都塞到一個(gè) sandbox
對(duì)象里,而 Sandbox
對(duì)象也需要定義在全局,存在被覆蓋的風(fēng)險(xiǎn)。愛(ài)掏網(wǎng) - it200.com模塊化需要保證全局變量盡量干凈,目前為止的模塊化方案都沒(méi)有很好的做到這一點(diǎn)。愛(ài)掏網(wǎng) - it200.com
依賴注入 (2009): 就是大家熟知的 angular1.0,依賴注入的思想現(xiàn)在已廣泛運(yùn)用在 react、vue 等流行框架中。愛(ài)掏網(wǎng) - it200.com但依賴注入和解決模塊化問(wèn)題還差得遠(yuǎn)。愛(ài)掏網(wǎng) - it200.com
CommonJS (2009): 真正解決模塊化問(wèn)題,從 node 端逐漸發(fā)力到前端,前端需要使用構(gòu)建工具模擬。愛(ài)掏網(wǎng) - it200.com
Amd (2009): 都是同一時(shí)期的產(chǎn)物,這個(gè)方案主要解決前端動(dòng)態(tài)加載依賴,相比 commonJs,體積更小,按需加載。愛(ài)掏網(wǎng) - it200.com
Umd (2011): 兼容了 CommonJS 與 Amd,其核心思想是,如果在 commonjs 環(huán)境(存在 module.exports
,不存在 define
),將函數(shù)執(zhí)行結(jié)果交給 module.exports
實(shí)現(xiàn) Commonjs,否則用 Amd 環(huán)境的 define
,實(shí)現(xiàn) Amd。愛(ài)掏網(wǎng) - it200.com
Labeled Modules (2012): 和 Commonjs 很像了,沒(méi)什么硬傷,但生不逢時(shí),碰上 Commonjs 與 Amd,那只有被人遺忘的份了。愛(ài)掏網(wǎng) - it200.com
YModules (2024): 既然都出了 Commonjs Amd,文章還列出了此方案,一定有其獨(dú)到之處。愛(ài)掏網(wǎng) - it200.com其核心思想在于使用 provide
取代 return
,可以控制模塊結(jié)束時(shí)機(jī),處理異步結(jié)果;拿到第二個(gè)參數(shù) module
,修改其他模塊的定義(雖然很有拓展性,但用在項(xiàng)目里是個(gè)攪屎棍)。愛(ài)掏網(wǎng) - it200.com
ES2024 Modules (2024): 就是我們現(xiàn)在的模塊化方案,還沒(méi)有被瀏覽器實(shí)現(xiàn),大部分項(xiàng)目已通過(guò) babel
或 typescript
提前體驗(yàn)。愛(ài)掏網(wǎng) - it200.com
3 精讀
本次提出獨(dú)到觀點(diǎn)的同學(xué)有:流形,黃子毅,蘇里約,camsong,楊森,淡蒼,留影,精讀由此歸納。愛(ài)掏網(wǎng) - it200.com
從語(yǔ)言層面到文件層面的模塊化
從 1999 年開始,模塊化探索都是基于語(yǔ)言層面的優(yōu)化,真正的革命從 2009 年 CommonJS 的引入開始,前端開始大量使用預(yù)編譯。愛(ài)掏網(wǎng) - it200.com
這篇文章所提供的模塊化歷史的方案都是邏輯模塊化,從 CommonJS 方案開始前端把服務(wù)端的解決方案搬過(guò)來(lái)之后,算是看到標(biāo)準(zhǔn)物理與邏輯統(tǒng)一的模塊化。愛(ài)掏網(wǎng) - it200.com但之后前端工程不得不引入模塊化構(gòu)建這一步。愛(ài)掏網(wǎng) - it200.com正是這一步給前端開發(fā)無(wú)疑帶來(lái)了諸多的不便,尤其是現(xiàn)在我們開發(fā)過(guò)程中經(jīng)常為了優(yōu)化這個(gè)工具帶了很多額外的成本。愛(ài)掏網(wǎng) - it200.com
從 CommonJS 之前其實(shí)都只是封裝,并沒(méi)有一套模塊化規(guī)范,這個(gè)就有些像類與包的概念。愛(ài)掏網(wǎng) - it200.com我在10年左右用的最多的還是 YUI2,YUI2 是用 namespace 來(lái)做模塊化的,但有很多問(wèn)題沒(méi)有解決,比如多版本共存,因此后來(lái) YUI3 出來(lái)了。愛(ài)掏網(wǎng) - it200.com
YUI().use('node', 'event', function (Y) {
// The Node and Event modules are loaded and ready to use.
// Your code goes here!
});
YUI3 的 sandbox 像極了差不多同時(shí)出現(xiàn)的 AMD 規(guī)范,但早期 yahoo 在前端圈的影響力還是很大的,而 requirejs 到 2011 年才誕生,因此圈子不是用著 YUI 要不就自己封裝一套 sandbox,內(nèi)部使用 jQuery。愛(ài)掏網(wǎng) - it200.com
為什么模塊化方案這么晚才成型,可能早期應(yīng)用的復(fù)雜度都在后端,前端都是非常簡(jiǎn)單邏輯。愛(ài)掏網(wǎng) - it200.com后來(lái) Ajax 火了之后,web app 概念的開始流行,前端的復(fù)雜度也呈指數(shù)級(jí)上漲,到今天幾乎和后端接近一個(gè)量級(jí)。愛(ài)掏網(wǎng) - it200.com工程發(fā)展到一定階段,要出現(xiàn)的必然會(huì)出現(xiàn)。愛(ài)掏網(wǎng) - it200.com
前端三劍客的模塊化展望
從 js 模塊化發(fā)展史,我們還看到了 css html 模塊化方面的嚴(yán)重落后,如今依賴編譯工具的模塊化增強(qiáng)在未來(lái)會(huì)被標(biāo)準(zhǔn)所替代。愛(ài)掏網(wǎng) - it200.com
原生支持的模塊化,解決 html 與 css 模塊化問(wèn)題正是以后的方向。愛(ài)掏網(wǎng) - it200.com
再回到 JS 模塊化這個(gè)主題,開頭也說(shuō)到是為了構(gòu)建 scope,實(shí)則提供了業(yè)務(wù)規(guī)范標(biāo)準(zhǔn)的輸入輸出的方式。愛(ài)掏網(wǎng) - it200.com但文章中的 JS 的模塊化還不等于前端工程的模塊化,Web 界面是由 HTML、CSS 和 JS 三種語(yǔ)言實(shí)現(xiàn),不論是 CommonJS 還是 AMD 包括之后的方案都無(wú)法解決 CSS 與 HTML 模塊化的問(wèn)題。愛(ài)掏網(wǎng) - it200.com
對(duì)于 CSS 本身它就是 global scope,因此開發(fā)樣式可以說(shuō)是喜憂參半。愛(ài)掏網(wǎng) - it200.com近幾年也涌現(xiàn)把 HTML、CSS 和 JS 合并作模塊化的方案,其中 react/css-modules 和 vue 都為人熟知。愛(ài)掏網(wǎng) - it200.com當(dāng)然,這一點(diǎn)還是非常依賴于 webpack/rollup 等構(gòu)建工具,讓我們意識(shí)到在 browser 端還有很多本質(zhì)的問(wèn)題需要推進(jìn)。愛(ài)掏網(wǎng) - it200.com
對(duì)于 css 模塊化,目前不依賴預(yù)編譯的方式是 styled-component
,通過(guò) js 動(dòng)態(tài)創(chuàng)建 class。愛(ài)掏網(wǎng) - it200.com而目前 css 也引入了與 js 通信的機(jī)制 與 原生變量支持。愛(ài)掏網(wǎng) - it200.com未來(lái) css 模塊化也很可能是運(yùn)行時(shí)的,所以目前比較看好 styled-component
的方向。愛(ài)掏網(wǎng) - it200.com
對(duì)于 html 模塊化,小尤最近爆出與 chrome 小組調(diào)研 html Modules,如果 html 得到了瀏覽器,編輯器的模塊化支持,未來(lái)可能會(huì)取代 jsx 成為最強(qiáng)大的模塊化、模板語(yǔ)言。愛(ài)掏網(wǎng) - it200.com
對(duì)于 js 模塊化,最近出現(xiàn)的