前端“智能”靜態資源管理 - Onebox - 博客園

前端“智能”靜態資源管理

  模塊化/組件化開發,僅僅描述了一種開發理念,也可以認為是一種開發規范,倘若你認可這規范,對它的分治策略產生了共鳴,那我們就可以繼續聊聊它的具體實現了。

  很明顯,模塊化/組件化開發之后,我們最終要解決的,就是模塊/組件加載的技術問題。然而前端與客戶端GUI軟件有一個很大的不同:

前端是一種遠程部署,運行時增量下載的GUI軟件

  前端應用沒有安裝過程,其所需程序資源都部署在遠程服務器,用戶使用瀏覽器訪問不同的頁面來加載不同的資源,隨著頁面訪問的增加,漸進式的將整個程序下載到本地運行,“增量下載”是前端在工程上有別于客戶端GUI軟件的根本原因。

  上圖展示了一款界面繁多功能豐富的應用,如果采用Web實現,相信也是不小的體量,如果用戶第一次訪問頁面就強制其加載全站靜態資源再展示,相信會有很多用戶因為失去耐心而流失。根據“增量”的原則,我們應該精心規劃每個頁面的資源加載策略,使得用戶無論訪問哪個頁面都能按需加載頁面所需資源,沒訪問過的無需加載,訪問過的可以緩存復用,最終帶來流暢的應用體驗。

  這正是Web應用“免安裝”的魅力所在。

  由“增量”原則引申出的前端優化技巧幾乎成為了性能優化的核心,有加載相關的按需加載、延遲加載、預加載、請求合并等策略;有緩存相關的瀏覽器緩存利用,緩存更新、緩存共享、非覆蓋式發布等方案;還有復雜的BigRender、BigPipe、Quickling、PageCache等技術。這些優化方案無不圍繞著如何將增量原則做到極致而展開。

所以我覺得:

前端開發最迫切需要做好的就是在基礎架構中貫徹增量原則。

  相信這種貫徹不會隨著時間的推移而改變,在可預見的未來,無論在HTTP1.x還是HTTP2.0時代,無論在ES5亦或者ES6/7時代,無論是AMD/CommonJS/UMD亦或者ES6 module時代,無論端內技術如何變遷,我們都有足夠充分的理由要做好前端程序資源的增量加載。

  我覺得是在其基礎架構中缺少這樣一種“智能”的資源加載方案。沒有這樣的方案,很難將前端應用的規模發展到第四階段,很難實現落地前面介紹的那種組件化開發方案,也很難讓多方合作高效率的完成一項大型應用的開發,并保證其最終運行性能良好。在第四階段,我們需要強大的工程化手段來管理”玩具般簡單“的前端開發。

  在我的印象中,Facebook是這方面探索的偉大先驅之一,早在2010年的Velocity China大會上,來自Facebook的David Wei博士就為業界展示了他們令人驚艷的靜態網頁資源管理和優化技術。

David Wei博士在當年的交流會上提到過一些關于Facebook的一些產品數據:

Facebook整站有10000+個靜態資源;

每個靜態資源都有可能被翻譯成超過100種語言版本;

每種資源又會針對瀏覽器生成3種不同的版本;

要針對不同帶寬的用戶做5種不同的打包方法;

有3、4個不同的用戶組,用于小批次體驗新的產品功能;

還要考慮不同的送達方法,可以直接送達,或者通過iframe的方式提升資源并行加載的速度;

靜態資源的壓縮和非壓縮狀態可切換,用于調試和定位線上問題

  這是一個狀態爆炸的問題,將所有狀態乘起來,整個網站的資源組合方式會達到幾百萬種之多(去重之后統計大概有300萬種組合方式)。支撐這么大規模前端項目運行的底層架構正是魏博士在那次演講中分享的Static Resource Management System(靜態資源管理系統),用以解決Facebook項目中有關前端工程的3D問題(Development,Deployment,Debugging)。

  那段時間?FIS?項目正好遇到瓶頸,當時的FIS還是一個用php寫的task-based構建工具,那時候對于前端工程的認知度很低,覺得前端構建不就是幾個壓縮優化校驗打包任務的組合嗎,寫好流程調度,就針對不同需求寫插件唄,看似非常簡單。但當我們支撐越來越多的業務團隊,接觸到各種不同的業務場景時,我們深刻的感受到task-based工具的粗糙,團隊每天疲于根據各種業務場景編寫各種打包插件,構建邏輯異常復雜,隱隱看到不可控的跡象。

  我們很快意識到把基礎架構放到構建工具中實現是一件很愚蠢的事,試圖依靠構建工具實現各種優化策略使得構建變成了一個巨大的黑盒,一旦發生問題,定位起來非常困難,而且每種業務場景都有不同的優化需求,構建工具只能通過靜態分析來優化加載,具有很大的局限性,單頁面/多頁面/PC端/移動端/前端渲染/后端渲染/多語言/多皮膚/高級優化等等資源加載問題,總不能給每個都寫一套工具吧,更何況這些問題彼此之間還可以有多種組合應用,工具根本寫不過來。

  Facebook的做法無疑為我們亮起了一盞明燈,不過可惜它并不開源(不是技術封鎖,而是這個系統依賴FB體系中的其他方面,通用性不強,開源意義不大),我們只能嘗試挖掘相關信息,網上對它的完整介紹還是非常非常少,分析facebook的前端代碼也沒有太多收獲,后來無意中發現了facebook使用的項目管理工具phabricator中的一個靜態管理方案Celerity,以及相關的說明,看它的描述很像是Facebook靜態資源管理系統的一個mini版!

  簡單看過整個系統之后發現原理并不復雜(小而美的典范),它是通過一個小工具掃描所有靜態資源,生成一張資源表,然后有一個PHP實現的資源管理框架(Celerity)提供了資源加載接口,替代了傳統的script/link等靜態的資源加載標簽,最終通過查表來加載資源。

雖然沒有真正看過FB的那套系統,但眼前的這個小小的框架給了當時的我們足夠多的啟示:

靜態資源管理系統 = 資源表 + 資源加載框架

  多么優雅的實現啊!

  資源表是一份數據文件(比如JSON),是項目中所有靜態資源(主要是JS和CSS)的構建信息記錄,通過構建工具掃描項目源碼生成,是一種k-v結構的數據,以每個資源的id為key,記錄了資源的類別、部署路徑、依賴關系、打包合并等內容,比如:

{

"a.js": {

"url": "/static/js/a.5f100fa.js",

"dep": [ "b.js", "a.css" ]

},

"a.css": {

"url": "/static/css/a.63cf374.css",

"dep": [ "button.css" ]

},

"b.js": {

"url": "/static/js/b.97193bf.js"

},

"button.css": {

"url": "/static/css/button.de33108.js"

}

}

  而資源加載框架則提供一些資源引用的API,讓開發者根據id來引用資源,替代靜態的script/link標簽來收集、去重、按需加載資源。調用這些接口時,框架通過查表來查找資源的各項信息,并遞歸查找其依賴的資源的信息,然后我們可以在這個過程中實現各種性能優化算法來“智能”加載資源。

  根據業務場景的不同,加載框架可以在瀏覽器中用JS實現,也可以是后端模板引擎中用服務端語言實現,甚至二者的組合,不一而足。

  這種設計很快被驗證具有足夠的靈活性,能夠完美支撐不同團隊不同技術規范下的性能優化需求,前面提到的按需加載、延遲加載、預加載、請求合并、文件指紋、CDN部署、Bigpipe、Quickling、BigRender、首屏CSS內嵌、HTTP 2.0服務端推送等等性能優化手段都可以很容易的在這種架構上實現,甚至可以根據性能日志自動進行優化(Facebook已實現)。

  因為有了資源表,我們可以很方便的控制資源加載,通過各種手段在運行時計算頁面的資源使用情況,從而獲得最佳加載性能。無論是前端渲染的單頁面應用,還是后端渲染的多頁面應用,這種方法都同樣適用。

  此外,它還很巧妙的約束了構建工具的職責——只生成資源表。資源表是非常通用的數據結構,無論什么業務場景,其業務代碼最終都可以被掃描為相同結構的表數據,并標記資源間的依賴關系,有了表之后我們只需根據不同的業務場景定制不同的資源加載框架就行了,從此徹底告別一個團隊維護一套工具的時代!!!

恩,如你所見,雖然徹底告別了一個團隊一套工具的時代,但似乎又進入了一個團隊一套框架的時代。其實還是有差別的,因為框架具有很大的靈活性,而且不那么黑盒,采用框架實現資源管理相比構建更容易調試、定位和升級變更。

  深耕靜態資源加載框架可以帶來許多收益,而且有足夠的靈活性和健壯性面向未來的技術變革,這個我們留作后話。

  本文來自http://github.com/fouber/blog,著作權屬于原作者@前端農名工。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/248937.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/248937.shtml
英文地址,請注明出處:http://en.pswp.cn/news/248937.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【轉】幾張圖看懂列式存儲

幾張圖看懂列式存儲 轉載于:https://www.cnblogs.com/apeway/p/10870211.html

hive -e和hive -f的區別(轉)

大家都知道,hive -f 后面指定的是一個文件,然后文件里面直接寫sql,就可以運行hive的sql,hive -e 后面是直接用雙引號拼接hivesql,然后就可以執行命令。 但是,有這么一個東西,我的sql當中有一個s…

我們是如何做好前端工程化和靜態資源管理 - 無雄 - 博客園

我們是如何做好前端工程化和靜態資源管理 隨著互聯網的發展,我們的業務也日益變得更加復雜且多樣化起來,前端工程師也不再只是做簡單的頁面開發這么簡單,我們需要面對的十分復雜的系統性問題,例如,業務愈來愈復雜&…

Mybatis-plus之RowBounds實現分頁查詢

物理分頁和邏輯分頁 物理分頁:直接從數據庫中拿出我們需要的數據,例如在Mysql中使用limit。 邏輯分頁:從數據庫中拿出所有符合要求的數據,然后再從這些數據中拿到我們需要的分頁數據。 優缺點 物理分頁每次都要訪問數據庫&#xf…

常見的6種JavaScript設計模式

常見的6種JavaScript設計模式 構造函數模式 /*** 構造一個動物的函數 */ function Animal(name, color){this.name name;this.color color;this.getName function(){return this.name;} } // 實例一個對象 var cat new Animal(貓, 白色); console.log( cat.getName() );工…

峰度(Kurtosis)和偏度(Skewness)

峰度(Kurtosis) 定義峰度又稱峰態系數,表征概率密度分布曲線在平均值處峰值高低的特征數,即是描述總體中所有取值分布形態陡緩程度的統計量。直觀看來,峰度反映了峰部的尖度。這個統計量需要與正態分布相比較。 公式定…

1.27

測試程序提出問題并解決轉載于:https://www.cnblogs.com/JustinTimberlake/p/10028870.html

javascript設計模式系列 - LukeLin - 博客園

javascript設計模式系列 創建型: 1.抽象工廠模式(Abstract Factory) 2.構建者模式(Builder) 3.工廠方法模式(Factory Method) 4.原型模式(Prototype) 5.單例模式&a…

多功能嵌入式解碼軟件(2)

多功能嵌入式解碼軟件(2) 驗證類庫 通信協議 下面進行一個示例: 下位機需要向上位機發送3中數據幀,數據幀以功能碼來識別,每種數據幀的協議如下3個表格所示,上位機需要把這些數據按照協議解碼出來&#xff…

vue項目如何打包扔向服務器 - Hi-Sen - 博客園

當我們將 vue 項目完成后,面臨的就是如何將項目進行打包上線,放到服務器中。我使用的是 vue-cli(simple) 腳手架,所以就講一下如何將項目進行打包,并放到 tomcat 上。 如果是 vue-cli (非 simple 腳手架…

MySQL備份與恢復-mysqldump備份與恢復

這片博文主要用來介紹MySQL的備份與恢復: MySQL的備份形式可以分為如下幾種: 熱備----即不停機備份冷備----需要關閉MySQL,然后備份其數據文件。(停機備份一般是直接拷貝其datadir目錄)溫備----在線備份,對…

第六次實訓作業異常處理

第六次實訓作業異常處理 編寫一個類ExceptionTest,在main方法中使用try-catch-finally語句結構實現:在try語句塊中,編寫兩個數相除操作,相除的兩個操作數要求程序運行時用戶輸入;在catch語句塊中,捕獲被0除…

k8s學習筆記-調度之Affinity

Kubernetes中的調度策略可以大致分為兩種 一種是全局的調度策略,要在啟動調度器時配置,包括kubernetes調度器自帶的各種predicates和priorities算法,具體可以參看上一篇文章; 另一種是運行時調度策略,包括nodeAffinity…

vue-cli webpack配置分析 - chenBright - SegmentFault 思否

相信vue使用者對vue-cli都不會陌生,甚至可以說,很熟悉了,但對其webpack的配置可能知之甚少吧。 過完年回來后,我接手了公司的新項目。新項目是一個spa。很自然,我就想到了vue-cli腳手架了,當時研究一下它的…

[Xcode 實際操作]六、媒體與動畫-(6)使用UIBlurEffect給圖片添加模糊效果

目錄:[Swift]Xcode實際操作 本文將演示如何給圖像添加模糊效果。 在項目導航區,打開視圖控制器的代碼文件【ViewController.swift】 1 import UIKit2 3 class ViewController: UIViewController {4 5 override func viewDidLoad() {6 super.…

MapReduce編程實踐

一、MapReduce編程思想 學些MapRedcue主要是學習它的編程思想,在MR的編程模型中,主要思想是把對數據的運算流程分成map和reduce兩個階段: Map階段:讀取原始數據,形成key-value數據(map方法)。即…

webpack基礎+webpack配置文件常用配置項介紹+webpack-dev-server - QxQstar - 博客園

一.webpack基礎 1.在項目中生成package.json:在項目根目錄中輸入npm init,根據提示輸入相應信息。(也可以不生成package.json文件,但是package.json是很有用的,所有建議生成) 2.安裝webpaack a.在全局中安裝…

(十)

空轉載于:https://www.cnblogs.com/shanae/p/10034479.html

編譯原理--NFA/DFA

現成的, 講義: https://www.cnblogs.com/AndyEvans/p/10240790.html https://www.cnblogs.com/AndyEvans/p/10241031.html 一個例子, 寫得非常好. 一下子就全明白了, 尤其是像我這種沒有聽過編譯原理課程的人. https://blog.csdn.net/tyler_download/article/details/53139240 …

Python中pass的用法

空語句 do nothing保證格式完整保證語義完整以if語句為例,在c或c/java中: if(true); //do nothingelse{ //do something}對應于python就要這樣寫: if true: pass #do nothingelse: #do something 1 pass語句在函數中的作用當你在編寫一個程序…