摘要:我是這一期的主持人黃子毅本期精讀的文章是。模塊化需要保證全局變量盡量干凈,目前為止的模塊化方案都沒有很好的做到這一點。精讀本次提出獨到觀點的同學有流形,黃子毅,蘇里約,,楊森,淡蒼,留影,精讀由此歸納。
這次是前端精讀期刊與大家第一次正式碰面,我們每周會精讀并分析若干篇精品好文,試圖討論出結論性觀點。沒錯,我們試圖通過觀點的碰撞,爭做無主觀精品好文的意見領袖。
我是這一期的主持人 —— 黃子毅
本期精讀的文章是:evolutionOfJsModularity。
懶得看文章?沒關系,稍后會附上文章內容概述,同時,更希望能通過閱讀這一期的精讀,穿插著深入閱讀原文。
1 引言如今,Javascript 模塊化規范非常方便、自然,但這個新規范僅執行了2年,就在 4 年前,js 的模塊化還停留在運行時支持,10 年前,通過后端模版定義、注釋定義模塊依賴。對經歷過來的人來說,歷史的模塊化方式還停留在腦海中,反而新上手的同學會更快接受現代的模塊化規范。
但為什么要了解 Javascript 模塊化發展的歷史呢?因為凡事都有兩面性,了解 Javascript 模塊化規范,有利于我們思考出更好的模塊化方案,縱觀歷史,從 1999 年開始,模塊化方案最多維持兩年,就出現了新的替代方案,比原有的模塊化更清晰、強壯,我們不能被現代模塊化方式限制住思維,因為現在的 ES2015 模塊化方案距離發布也僅僅過了兩年。
2 內容概要直接定義依賴 (1999): 由于當時 js 文件非常簡單,模塊化方式非常簡單粗暴 —— 通過全局方法定義、引用模塊。這種定義方式與現在的 commonjs 非常神似,區別是 commonjs 以文件作為模塊,而這種方法可以在任何文件中定義模塊,模塊不與文件關聯。
閉包模塊化模式 (2003): 用閉包方式解決了變量污染問題,閉包內返回模塊對象,只需對外暴露一個全局變量。
模版依賴定義 (2006): 這時候開始流行后端模版語法,通過后端語法聚合 js 文件,從而實現依賴加載,說實話,現在 go 語言等模版語法也很流行這種方式,寫后端代碼的時候不覺得,回頭看看,還是掛在可維護性上。
注釋依賴定義 (2006): 幾乎和模版依賴定義同時出現,與 1999 年方案不同的,不僅僅是模塊定義方式,而是終于以文件為單位定義模塊了,通過 lazyjs 加載文件,同時讀取文件注釋,繼續遞歸加載剩下的文件。
外部依賴定義 (2007): 這種定義方式在 cocos2d-js 開發中普遍使用,其核心思想是將依賴抽出多帶帶文件定義,這種方式不利于項目管理,畢竟依賴抽到代碼之外,我是不是得兩頭找呢?所以才有通過 webpack 打包為一個文件的方式暴力替換為 commonjs 的方式出現。
Sandbox模式 (2009): 這種模塊化方式很簡單,暴力,將所有模塊塞到一個 sanbox 變量中,硬傷是無法解決明明沖突問題,畢竟都塞到一個 sandbox 對象里,而 Sandbox 對象也需要定義在全局,存在被覆蓋的風險。模塊化需要保證全局變量盡量干凈,目前為止的模塊化方案都沒有很好的做到這一點。
依賴注入 (2009): 就是大家熟知的 angular1.0,依賴注入的思想現在已廣泛運用在 react、vue 等流行框架中。但依賴注入和解決模塊化問題還差得遠。
CommonJS (2009): 真正解決模塊化問題,從 node 端逐漸發力到前端,前端需要使用構建工具模擬。
Amd (2009): 都是同一時期的產物,這個方案主要解決前端動態加載依賴,相比 commonJs,體積更小,按需加載。
Umd (2011): 兼容了 CommonJS 與 Amd,其核心思想是,如果在 commonjs 環境(存在 module.exports,不存在 define),將函數執行結果交給 module.exports 實現 Commonjs,否則用 Amd 環境的 define,實現 Amd。
Labeled Modules (2012): 和 Commonjs 很像了,沒什么硬傷,但生不逢時,碰上 Commonjs 與 Amd,那只有被人遺忘的份了。
YModules (2013): 既然都出了 Commonjs Amd,文章還列出了此方案,一定有其獨到之處。其核心思想在于使用 provide 取代 return,可以控制模塊結束時機,處理異步結果;拿到第二個參數 module,修改其他模塊的定義(雖然很有拓展性,但用在項目里是個攪屎棍)。
ES2015 Modules (2015): 就是我們現在的模塊化方案,還沒有被瀏覽器實現,大部分項目已通過 babel 或 typescript 提前體驗。
3 精讀本次提出獨到觀點的同學有:流形,黃子毅,蘇里約,camsong,楊森,淡蒼,留影,精讀由此歸納。
從語言層面到文件層面的模塊化從 1999 年開始,模塊化探索都是基于語言層面的優化,真正的革命從 2009 年 CommonJS 的引入開始,前端開始大量使用預編譯。
這篇文章所提供的模塊化歷史的方案都是邏輯模塊化,從 CommonJS 方案開始前端把服務端的解決方案搬過來之后,算是看到標準物理與邏輯統一的模塊化。但之后前端工程不得不引入模塊化構建這一步。正是這一步給前端開發無疑帶來了諸多的不便,尤其是現在我們開發過程中經常為了優化這個工具帶了很多額外的成本。
從 CommonJS 之前其實都只是封裝,并沒有一套模塊化規范,這個就有些像類與包的概念。我在10年左右用的最多的還是 YUI2,YUI2 是用 namespace 來做模塊化的,但有很多問題沒有解決,比如多版本共存,因此后來 YUI3 出來了。
YUI().use("node", "event", function (Y) { // The Node and Event modules are loaded and ready to use. // Your code goes here! });
YUI3 的 sandbox 像極了差不多同時出現的 AMD 規范,但早期 yahoo 在前端圈的影響力還是很大的,而 requirejs 到 2011 年才誕生,因此圈子不是用著 YUI 要不就自己封裝一套 sandbox,內部使用 jQuery。
為什么模塊化方案這么晚才成型,可能早期應用的復雜度都在后端,前端都是非常簡單邏輯。后來 Ajax 火了之后,web app 概念的開始流行,前端的復雜度也呈指數級上漲,到今天幾乎和后端接近一個量級。工程發展到一定階段,要出現的必然會出現。
從 js 模塊化發展史,我們還看到了 css html 模塊化方面的嚴重落后,如今依賴編譯工具的模塊化增強在未來會被標準所替代。
原生支持的模塊化,解決 html 與 css 模塊化問題正是以后的方向。
再回到 JS 模塊化這個主題,開頭也說到是為了構建 scope,實則提供了業務規范標準的輸入輸出的方式。但文章中的 JS 的模塊化還不等于前端工程的模塊化,Web 界面是由 HTML、CSS 和 JS 三種語言實現,不論是 CommonJS 還是 AMD 包括之后的方案都無法解決 CSS 與 HTML 模塊化的問題。
對于 CSS 本身它就是 global scope,因此開發樣式可以說是喜憂參半。近幾年也涌現把 HTML、CSS 和 JS 合并作模塊化的方案,其中 react/css-modules 和 vue 都為人熟知。當然,這一點還是非常依賴于 webpack/rollup 等構建工具,讓我們意識到在 browser 端還有很多本質的問題需要推進。
對于 css 模塊化,目前不依賴預編譯的方式是 styled-component,通過 js 動態創建 class。而目前 css 也引入了與 js 通信的機制 與 原生變量支持。未來 css 模塊化也很可能是運行時的,所以目前比較看好 styled-component 的方向。
對于 html 模塊化,小尤最近爆出與 chrome 小組調研 html Modules,如果 html 得到了瀏覽器,編輯器的模塊化支持,未來可能會取代 jsx 成為最強大的模塊化、模板語言。
對于 js 模塊化,最近出現的 方式,雖然還沒有得到瀏覽器原生支持,但也是我比較看好的未來趨勢,這樣就連 webpack 的拆包都不需要了,直接把源代碼傳到服務器,配合 http2.0 完美拋開預編譯的枷鎖。
上述三中方案都不依賴預編譯,分別實現了 html、css、js 模塊化,相信這就是未來。
模塊化標準推進速度仍然緩慢2015 年提出的標準,在 17 年依然沒有得到實現,即便在 nodejs 端。
這幾年 TC39 對語言終于重視起來了,慢慢有動作了,但針對模塊標準制定的速度,與落實都非常緩慢,與 javascript 越來越流行的趨勢逐漸脫節。nodejs 至今也沒有實現 ES2015 模塊化規范,所有 jser 都處在構建工具的陰影下。
Http 2.0 對 js 模塊化的推動js 模塊化定義的再美好,瀏覽器端的支持粒度永遠是瓶頸,http 2.0 正是考慮到了這個因素,大力支持了 ES 2015 模塊化規范。
幸運的是,模塊化構建將來可能不再需要。隨著 HTTP/2 流行起來,請求和響應可以并行,一次連接允許多個請求,對于前端來說宣告不再需要在開發和上線時再做編譯這個動作。
幾年前,模塊化幾乎是每個流行庫必造的輪子(YUI、Dojo、Angular),大牛們自己爽的同時其實造成了社區的分裂,很難積累。有了 ES2015 Modules 之后,JS 開發者終于可以像 Java 開始者十年前一樣使用一致的方式愉快的互相引用模塊。
不過 ES2015 Modules 也只是解決了開發的問題,由于瀏覽器的特殊性,還是要經過繁瑣打包的過程,等 Import,Export 和 HTTP 2.0 被主流瀏覽器支持,那時候才是徹底的模塊化。
Http 2.0 后就不需要構建工具了嗎?看到大家基本都提到了 HTTP/2,對這項技術解決前端模塊化及資源打包等工程問題抱有非常大的期待。很多人也認為 HTTP/2 普及后,基本就沒有 Webpack 什么事情了。
不過 Webpack 作者 @sokra 在他的文章 webpack & HTTP/2 里提到了一個新的 Webpack 插件 AggressiveSplittingPlugin。簡單的說,這款插件就是為了充分利用 HTTP/2 的文件緩存能力,將你的業務代碼自動拆分成若干個數十 KB 的小文件。后續若其中任意一個文件發生變化,可以保證其他的小 chunck 不需要重新下載。
可見,即使不斷的有新技術出現,也依然需要配套的工具來將前端工程問題解決方案推向極致。
模塊化是大型項目的銀彈嗎?只要遵循了最新模塊化規范,就可以使項目具有最好的可維護性嗎? Js 模塊化的目的是支持前端日益上升的復雜度,但絕不是唯一的解決方案。
分析下 JavaScript 為什么沒有模塊化,為什么又需要模塊化:這個 95 年被設計出來的時候,語言的開發者根本沒有想到它會如此的大放異彩,也沒有將它設計成一種模塊化語言。按照文中的說法,99 年也就是 4 年后開始出現了模塊化的需求。如果只有幾行代碼用模塊化是扯,初始的 web 開發業務邏輯都寫在 server 端,js 的作用小之又小。而現在 spa 都出現了,幾乎所有的渲染邏輯都在前端,如果還是沒有模塊化的組織,開發過程會越來越難,維護也是更痛苦。
文中已經詳細說明了模塊化的發展和優劣,這里不準備做過多的討論。我想說的是,在模塊化之后還有一個模塊間耦合的問題,如果模塊間耦合度大也會降低代碼的可重用性或者說復用性。所以也出現了降低耦合的觀察者模式或者發布/訂閱模式。這對于提升代碼重用,復用性和避免單點故障等都很重要。說到這里,還想順便提一下最近流行起來的響應式編程(RxJS),響應式編程中有一個很核心的概念就是 observable,也就是 Rx 中的流(stream)。它可以被 subscribe,其實也就是觀察者設計模式。
補充閱讀JavaScript 模塊化七日談
JavaScript模塊化編程簡史(2009-2016)
總結未來前端復雜度不斷增加已成定論,隨著后端成熟,自然會將焦點轉移到前端領域,而且服務化、用戶體驗越來越重要,前端體驗早不是當初能看就行,任何網頁的異常、視覺的差異,或文案的模糊,都會導致用戶流失,支付中斷。前端對公司營收的影響,漸漸與后端服務宕機同等嚴重,所以前端會越來越重,異常監控,性能檢測,工具鏈,可視化等等都是這幾年大家逐漸重視起來的。
我們早已不能將 javascript 早期玩具性質的模塊化方案用于現代越來越重要的系統中,前端界必然出現同等重量級的模塊化管理方案,感謝 TC39 制定的 ES2015 模塊化規范,我們已經離不開它,哪怕所有人必須使用 babel。
話說回來,標準推進的太慢,我們還是把編譯工具當作常態,抱著哪怕支持了 ES2015 所有特性,babel 依然還有用的心態,將預編譯進行到底。一句話,模塊化仍在路上。js 模塊化的矛頭已經對準了 css 與 html,這兩位元老也該向前衛的 js 學習學習了。
未來 css、html 的模塊化會自立門戶,還是賦予 js 更強的能力,讓兩者的模塊化依附于 js 的能力呢?目前 html 有自立門戶的苗頭(htmlModules),而 css 遲遲沒有改變,社區出現的 styled-component 已經用 js 將 css 模塊化得很好了,最新 css 規范也支持了與 js 的變量通信,難道希望依附于 js 嗎?這里希望得到大家更廣泛的討論。
我也認同,畢竟壓縮、混淆、md5、或者利用 nonce 屬性對 script 標簽加密,都離不開本地構建工具。
據說 http2 的優化中,有個最佳文件大小與數量的比例,那么還是脫離不了構建工具,前端未來會越來越復雜,同時也越來越美好。
至此,對于 javascript 模塊化討論已接近尾聲,對其優缺點也基本達成了一致。前端復雜度不斷提高,促使著模塊化的改進,代理(瀏覽器、node) 的支持程度,與前端特殊性(流量、緩存)可能前端永遠也離不開構建工具,新的標準會讓這些工作做的更好,同時取代、增強部分特征,前端的未來是更加美好的,復雜度也更高。
如果你想參與討論,請點擊這里,每周都有新的主題,每周五發布。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94761.html
摘要:大公司廣泛使用的開源庫,并且有一定國際影響力,而且大廠也有成功開源歷史經驗的話,就會增加說服力。總結下次技術選型討論時,可以拿出規則一條一條比對了然后技術選型只是基礎庫,利用這些基礎可以維護好自己的開源庫,把更多時間用在創造業務價值上。 1 引言 作者給出了從 12 個角度全面分析 JS 庫的可用性,分別是: 特性。 穩定性。 性能。 包生態。 社區。 學習曲線。 文檔。 工具。 發...
摘要:從社區和過往的經驗而言異步編程的難題已經基本解決無論是通過事件還是通過模式或者流程控制庫。本章主要介紹了主流的幾種異步編程解決方案這是目前中主要使用的方案。最后因為人們總是習慣性地以線性的方式進行思考以致異步編程相對較為難以掌握。 前言 如果你想要深入學習Node,那你不能錯過《深入淺出Node.js》這本書,它從不同的視角介紹了 Node 內在的特點和結構。由首章Node 介紹為索引...
摘要:官方規范估計很難出現現代框架的設計了,因為官方設計中前端三劍客是相互分離的方案,為了解決現階段前端框架的問題,必須由完全接管,這幾乎就是,或者支持語法的,可這與最初網頁設計思路是違背的。現代前端框架正在告訴我們新的三劍客虛擬虛擬。 1 引言 深入思考為何前端需要框架,以及 web components 是否可以代替前端框架? 原文地址,建議先閱讀原文,或者閱讀概述。 2 概述 現在前端...
摘要:精讀前端可以從多個角度理解,比如規范框架語言社區場景以及整條研發鏈路。同是前端未來展望,不同的文章側重的格局不同,兩個標題相同的文章內容可能大相徑庭。作為使用者,現在和未來的主流可能都是微軟系,畢竟微軟在操作系統方面人才儲備和經驗積累很多。 1. 引言 前端展望的文章越來越不好寫了,隨著前端發展的深入,需要擁有非常寬廣的視野與格局才能看清前端的未來。 筆者根據自身經驗,結合下面幾篇文章...
閱讀 25629·2021-09-29 09:41
閱讀 4787·2021-09-10 11:20
閱讀 1918·2021-09-09 09:32
閱讀 1881·2019-08-30 15:44
閱讀 3192·2019-08-29 17:13
閱讀 2809·2019-08-29 14:14
閱讀 2061·2019-08-29 14:11
閱讀 3221·2019-08-29 12:36