自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何高效地管理網(wǎng)站靜態(tài)資源

開發(fā) 前端
靜態(tài)資源管理系統(tǒng)的核心是對(duì)靜態(tài)資源進(jìn)行調(diào)度,可以很靈活的適應(yīng)各種性能優(yōu)化和差異化處理的場(chǎng)景,來(lái)達(dá)到更快、更可靠、低成本的自動(dòng)化項(xiàng)目交付。但是同時(shí)這個(gè)系統(tǒng)十分復(fù)雜,承載著各種職責(zé),這個(gè)系統(tǒng)本身會(huì)成為整個(gè)網(wǎng)站的關(guān)鍵節(jié)點(diǎn)和瓶頸。

背景

隨著互聯(lián)網(wǎng)開發(fā)和迭代速度越來(lái)越快,網(wǎng)站也變得越來(lái)越龐大,存在大量靜態(tài)資源,我們?cè)泄芾盱o態(tài)資源的方式變得越來(lái)越不適用,就如同封面圖一樣,靜態(tài)資源之間的關(guān)系錯(cuò)綜復(fù)雜,給工程師帶來(lái)了很多麻煩:

  • 人工管理依賴的噩夢(mèng),工程師需要頻繁管理和維護(hù)每個(gè)頁(yè)面需要的 JS & CSS 文件,包括靜態(tài)資源之間的依賴關(guān)系以及加載順序等。
  • 性能優(yōu)化成本高且不可持續(xù)性,為了提高網(wǎng)站性能,工程師總是在忙于優(yōu)化頁(yè)面靜態(tài)資源的加載,包括動(dòng)態(tài)加載靜態(tài)資源、按需加載靜態(tài)資源和修改靜態(tài)資源合并策略等,但是過(guò)了一段時(shí)間性能又降下來(lái)了,又需要周而復(fù)始的重復(fù)。
  • 靜態(tài)資源差異化的挑戰(zhàn),PC和無(wú)線的適配,不同的網(wǎng)絡(luò)和終端需要適配相應(yīng)的靜態(tài)資源;當(dāng)網(wǎng)站需要支持國(guó)際化的時(shí)候,需要對(duì)不同的國(guó)家進(jìn)行差異化處理,返回不同的靜態(tài)資源,這些需求對(duì)原有的靜態(tài)資源管理方式提出巨大挑戰(zhàn)。
  • 缺少快速迭代和試驗(yàn)新功能的有效支持,從開發(fā)到上線流程繁瑣,導(dǎo)致項(xiàng)目迭代周期長(zhǎng)

每天工程師都會(huì)提交大量的 new feature/bug fixes,每次項(xiàng)目發(fā)布和迭代都面臨著以上的問(wèn)題,是否可以有一套系統(tǒng)幫助我們管理/調(diào)度靜態(tài)資源來(lái)減少人工管理靜態(tài)資源成本和風(fēng)險(xiǎn),來(lái)達(dá)到更快、更可靠、低成本的自動(dòng)化項(xiàng)目交付。在實(shí)際項(xiàng)目開發(fā)中,我們進(jìn)行了大量探索和試驗(yàn),實(shí)現(xiàn)了一套 “靜態(tài)資源管理系統(tǒng)”,對(duì)靜態(tài)資源進(jìn)行全流程的管理和調(diào)度:

  • 幫助工程師管理靜態(tài)資源間的依賴以及資源的加載
  • 管理靜態(tài)資源版本更新與緩存,自動(dòng)處理CDN
  • 自動(dòng)生成最優(yōu)的靜態(tài)資源合并策略,實(shí)現(xiàn)網(wǎng)站自適應(yīng)優(yōu)化
  • 實(shí)現(xiàn)靜態(tài)資源的分級(jí)發(fā)布,快速迭代,輕松回滾
  • 根據(jù)國(guó)際化和終端的差異,送達(dá)不同的資源給不同的用戶

下面本文將會(huì)介紹我們是如何通過(guò)靜態(tài)資源系統(tǒng)來(lái)高效管理靜態(tài)資源的。

架構(gòu)

arc

靜態(tài)資源管理系統(tǒng)主要包含Compile、Sourcemap、Backend-Framework、Frontend-Loader幾個(gè)核心模塊:

  • Compile,對(duì)靜態(tài)資源進(jìn)行編譯處理,包括對(duì)靜態(tài)資源進(jìn)行預(yù)處理,url 處理(添加md5戳、添加CDN前綴),優(yōu)化(壓縮、合并),生成 Sourcemap 等
  • Sourcemap,在 compile 階段系統(tǒng)會(huì)掃描靜態(tài)資源,建立一張靜態(tài)資源關(guān)系表,記錄每個(gè)靜態(tài)資源的部署路徑以及依賴關(guān)系等信息
  • Backend-Framework,后端運(yùn)行時(shí)根據(jù)組件使用情況來(lái)調(diào)度靜態(tài)資源,為前端返回頁(yè)面渲染需要的資源。
  • Frontend-Loader,前端運(yùn)行時(shí)根據(jù)用戶的交互行為動(dòng)態(tài)請(qǐng)求靜態(tài)資源。

靜態(tài)資源管理系統(tǒng)通過(guò)自動(dòng)化工具對(duì)靜態(tài)資源進(jìn)行預(yù)處理并產(chǎn)出 Sourcemap,SourceMap 中記錄著靜態(tài)資源的調(diào)度信息,這樣框架在運(yùn)行時(shí)會(huì)根據(jù) SourceMap 中提供的調(diào)度信息自動(dòng)為用戶進(jìn)行靜態(tài)資源調(diào)度,不僅可以做到送達(dá)不同資源給不同用戶,還可以自適應(yīng)優(yōu)化靜態(tài)資源合并和加載。

自動(dòng)管理靜態(tài)資源依賴

靜態(tài)資源管理系統(tǒng)為工程師提供了聲明依賴關(guān)系的語(yǔ)法和規(guī)則,在 compile 階段系統(tǒng)會(huì)掃描靜態(tài)資源,建立一張靜態(tài)資源關(guān)系表,記錄每個(gè)靜態(tài)資源的部署路徑以及依賴關(guān)系等信息。

在html中聲明依賴

在項(xiàng)目的 index.html 里使用注釋聲明依賴關(guān)系:

  1. <!--  
  2.     @require demo.js  
  3.     @require "demo.css"  
  4. --> 

在 SourceMap 中則可看到:

  1. {  
  2.     "res" : {  
  3.         "demo.css" : {  
  4.             "uri" : "/static/css/demo_7defa41.css",  
  5.             "type" : "css"  
  6.         },  
  7.         "demo.js" : {  
  8.             "uri" : "/static/js/demo_33c5143.js",  
  9.             "type" : "js",  
  10.             "deps" : [ "demo.css" ]  
  11.         },  
  12.         "index.html" : {  
  13.             "uri" : "/index.html",  
  14.             "type" : "html",  
  15.             "deps" : [ "demo.js", "demo.css" ]  
  16.         }  
  17.     },  
  18.     "pkg" : {}  
  19. }  
  20.  

在js中聲明依賴

支持識(shí)別 js 文件中的 require 函數(shù),或者 注釋中的 @require 字段 標(biāo)記的依賴關(guān)系,這些分析處理對(duì) html 的 script 標(biāo)簽內(nèi)容 同樣有效。

  1. //demo.js  
  2. /**  
  3.  * @require demo.css  
  4.  * @require list.js  
  5.  */  
  6. var $ = require('jquery');  
  7.  

在SourceMap中則可看到:

  1. {  
  2.     "res" : {  
  3.         ...  
  4.         "demo.js" : {  
  5.             "uri" : "/static/js/demo_33c5143.js",  
  6.             "type" : "js",  
  7.             "deps" : [ "demo.css", "list.js", "jquery" ]  
  8.         },  
  9.         ...  
  10.     },  
  11.     "pkg" : {}  
  12. }  
  13.  

在css中聲明依賴

支持識(shí)別 css 文件 注釋中的 @require 字段 標(biāo)記的依賴關(guān)系,這些分析處理對(duì) html 的 style 標(biāo)簽內(nèi)容 同樣有效。

  1. //demo.js  
  2. /**  
  3.  * @require demo.css  
  4.  * @require list.js  
  5.  */  
  6. var $ = require('jquery');  
  7.  

在SourceMap中則可看到:

  1. {  
  2.     "res" : {  
  3.         ...  
  4.         "demo.js" : {  
  5.             "uri" : "/static/js/demo_33c5143.js",  
  6.             "type" : "js",  
  7.             "deps" : [ "demo.css", "list.js", "jquery" ]  
  8.         },  
  9.         ...  
  10.     },  
  11.     "pkg" : {}  
  12. }  
  13.  

#p#

按需加載靜態(tài)資源

在靜態(tài)資源管理系統(tǒng)接管了項(xiàng)目中的靜態(tài)資源后,可以知道靜態(tài)資源的運(yùn)行情況以及依賴關(guān)系,然后可以做到自動(dòng)為頁(yè)面按需加載靜態(tài)資源,下面通過(guò)一個(gè)例子來(lái)詳細(xì)講解:

sidebar.tpl 中的內(nèi)容如下,

  1. <!--  
  2.     @require "common:ui/dialog/dialog.css"  
  3. --> 
  4.  
  5. <a id="btn-navbar" class="btn-navbar"> 
  6.     <span class="icon-bar"></span> 
  7.     <span class="icon-bar"></span> 
  8.     <span class="icon-bar"></span> 
  9. </a> 
  10.  
  11. {script}  
  12.     var sidebar = require("common:ui/dialog/dialog.js");  
  13.     sidebar.run();  
  14. {/script}  
  15.  
  16. {script}  
  17.     $('a.btn-navbar').click(function() {  
  18.         require.async('common:ui/dialog/dialog.async.js', function( dialog ) {  
  19.             dialog.run();  
  20.         });  
  21.     });  
  22. {/script}  
  23.  

對(duì)項(xiàng)目編譯后,自動(dòng)化工具會(huì)分析依賴關(guān)系,并生成 sourcemap,如下

  1. "common:widget/sidebar/sidebar.tpl": {  
  2.     "uri": "common/widget/sidebsr/sidebar.tpl",  
  3.     "type": "tpl",  
  4.     "extras": {  
  5.         "async": [  
  6.             "common:ui/dialog/dialog.async.js"  
  7.         ]  
  8.     },  
  9.     "deps": [  
  10.         "common:ui/dialog/dialog.js",  
  11.         "common:ui/dialog/dialog.css"  
  12.     ]  
  13. }  
  14.  

在 sidebar 模塊被調(diào)用后,靜態(tài)資源管理系統(tǒng)通過(guò)查詢 sourcemap 可以得知,當(dāng)前 sidebar 模塊同步依賴 sidebar.js、sidebar.css,異步依賴 sdebar.async.js,在要輸出的 html 前面,生成靜態(tài)資源外鏈,我們得到最終的 html

  1. <link rel="stylesheet" href="/static/ui/dialog/dialog_7defa41.css"> 
  2.  
  3. <a id="btn-navbar" class="btn-navbar"> 
  4.     <span class="icon-bar"></span> 
  5.     <span class="icon-bar"></span> 
  6.     <span class="icon-bar"></span> 
  7. </a> 
  8.  
  9. <script type="text/javascript" src="/static/common/ui/dialog/dialog$12cd4.js"></script> 
  10. <script type="text/javascript"> 
  11.     require.resourceMap({  
  12.         "res": {  
  13.             "common:ui/dialog/dialog.async.js": {  
  14.                 "url": "/satic/common/ui/dialog/dialog.async_449e169.js"  
  15.             }  
  16.         }  
  17.     });  
  18. </script> 
  19. <script type="text/javascript"> 
  20.     var sidebar = require("common:ui/dialog/dialog.js");  
  21.     sidebar.run();  
  22.  
  23.     $('a.btn-navbar').click(function() {  
  24.         require.async('common:ui/dialog/dialog.async.js', function( dialog ) {  
  25.             dialog.run();  
  26.         });  
  27.     });  
  28. </script> 
  29.  

如上可見,后端模塊化框架將同步模塊的 script url 統(tǒng)一生成到頁(yè)面底部,將 css url 統(tǒng)一生成在 head 中,對(duì)于異步模塊(require.async)注冊(cè) resourceMap 代碼,框架會(huì)通過(guò) {script} 標(biāo)簽收集到頁(yè)面所有 script,統(tǒng)一管理并按順序輸出 script 到相應(yīng)位置。

當(dāng)我們想對(duì)模塊進(jìn)行打包,只需要使用一個(gè) pack 配置項(xiàng),對(duì)網(wǎng)站的靜態(tài)資源進(jìn)行打包,這樣在 SourceMap 中,所有被打包的資源會(huì)有一個(gè) pkg 屬性指向該表中的資源,而這個(gè)資源,正是我們配置的打包策略。這樣靜態(tài)資源系統(tǒng)可以根據(jù)對(duì)應(yīng)信息找到某個(gè)資源最終被合并后的 package 的 url,最后把這個(gè) url 返回給頁(yè)面。

自動(dòng)合并靜態(tài)資源

靜態(tài)資源管理系統(tǒng)可以根據(jù)產(chǎn)品線上靜態(tài)資源使用的數(shù)據(jù),自動(dòng)完成靜態(tài)資源合并工作,對(duì)工程師完全透明,解決手工維護(hù)的未及時(shí)排除廢棄資源、不可持續(xù)、成本大等問(wèn)題。

arc

詳情請(qǐng)見 靜態(tài)資源自動(dòng)合并;

靜態(tài)資源版本更新與緩存

靜態(tài)資源管理系統(tǒng)采用基于文件內(nèi)容的 hash 值來(lái)控制靜態(tài)資源的版本更新,如下所示:

  1. <script type="text/javascript" src="a_8244e91.js"></script> 
  2.  

其中”_82244e91 ”這串字符是根據(jù) a.js 的文件內(nèi)容進(jìn)行 hash 運(yùn)算得到的,只有文件內(nèi)容發(fā)生變化了才會(huì)有更改。這樣做的好處有:

  • 線上的 a.js 不是同名文件覆蓋,而是文件名 +hash 的冗余,所以可以先上線靜態(tài)資源,再上線 html 頁(yè)面,不存在間隙問(wèn)題;
  • 遇到問(wèn)題回滾版本的時(shí)候,無(wú)需回滾 a.js,只須回滾頁(yè)面即可;
  • 由于靜態(tài)資源版本號(hào)是文件內(nèi)容的 hash,因此所有靜態(tài)資源可以開啟永久強(qiáng)緩存,只有更新了內(nèi)容的文件才會(huì)緩存失效,緩存利用率大增;
  • 修改靜態(tài)資源后會(huì)在線上產(chǎn)生新的文件,一個(gè)文件對(duì)應(yīng)一個(gè)版本,因此不會(huì)受到構(gòu)造 CDN 緩存形式的攻擊

靜態(tài)資源管理系統(tǒng)會(huì)在 compile 階段識(shí)別文件中的定位標(biāo)記(url),計(jì)算對(duì)應(yīng)文件的 hash,并自動(dòng)替換為 '文件名 + hash',無(wú)需工程師手動(dòng)修改。

靜態(tài)資源分級(jí)控制

靜態(tài)資源管理系統(tǒng)可以對(duì)靜態(tài)資源做進(jìn)一步控制(Controlling Access to Features)以達(dá)到分級(jí)發(fā)布的效果,主要包括以下兩塊核心功能,

  • feature flags, 用來(lái)控制 feature 對(duì)應(yīng)的靜態(tài)資源是否加載
  • feature flippers, 可以靈活控制 feature,不僅僅是 on 或 off, 可以做到類似'3%用戶可以訪問(wèn)此功能'、'對(duì)內(nèi)部所有員工開放' 類似的效果

通過(guò)以上的控制我們可以輕松做到發(fā)布一個(gè)新功能,讓這個(gè)功能只對(duì)部分用戶可訪問(wèn),當(dāng)功能完善后對(duì)所有用戶開放,如果功能出現(xiàn)問(wèn)題直接一鍵回滾即可。

在項(xiàng)目中的類似代碼如下:

  1. {if $config.some eq 'Fred'}  
  2.     do something new and amazing here.  
  3. {elseif $config.some eq 'Wilma'}  
  4.     do the current boring stuff.  
  5. {else}  
  6.     whatever you are.  
  7.  

靜態(tài)資源管理系統(tǒng)會(huì)根據(jù)配置在運(yùn)行時(shí)對(duì) $config.some 進(jìn)行干預(yù).實(shí)現(xiàn)對(duì)靜態(tài)資源的訪問(wèn)權(quán)控制,通過(guò)運(yùn)行時(shí)的配置(feature flag)來(lái)控制靜態(tài)資源,還可以支持“主干開發(fā)”的方式,來(lái)達(dá)到更快的迭代速度。

我們還可以實(shí)現(xiàn)國(guó)際化的需求,原理同分級(jí)發(fā)布,在運(yùn)行時(shí)的做一些更細(xì)致的差異化處理

  1. {if $lang == 'zh-CN'}  
  2.     zh-CN  
  3. {/if}  
  4.  

總結(jié)

靜態(tài)資源管理系統(tǒng)的核心是對(duì)靜態(tài)資源進(jìn)行調(diào)度,可以很靈活的適應(yīng)各種性能優(yōu)化和差異化處理的場(chǎng)景,來(lái)達(dá)到更快、更可靠、低成本的自動(dòng)化項(xiàng)目交付。但是同時(shí)這個(gè)系統(tǒng)十分復(fù)雜,承載著各種職責(zé),這個(gè)系統(tǒng)本身會(huì)成為整個(gè)網(wǎng)站的關(guān)鍵節(jié)點(diǎn)和瓶頸。

作者:walter (http://weibo.com/u/1916384703) - F.I.S

原文鏈接:http://fex.baidu.com/blog/2014/04/fis-static-resource-management/

責(zé)任編輯:林師授 來(lái)源: 百度FEX
相關(guān)推薦

2009-09-09 15:24:06

2009-09-08 22:52:30

網(wǎng)絡(luò)流量管理

2010-08-18 09:58:57

網(wǎng)絡(luò)流量

2021-03-08 07:46:53

Git開源控制系統(tǒng)

2010-05-17 17:44:56

IIS6.0

2022-05-11 09:51:10

云計(jì)算公共云

2021-08-05 18:34:55

IntelliJ ID高效

2023-04-25 10:22:00

云計(jì)算網(wǎng)絡(luò)部署

2019-09-27 12:44:03

數(shù)據(jù)建模企業(yè)數(shù)據(jù)存儲(chǔ)

2021-05-31 07:57:00

拼接字符串Java

2009-07-27 13:32:37

2011-12-06 13:30:45

2023-11-28 08:22:05

goroutine語(yǔ)言

2019-03-22 14:20:26

管理多云云計(jì)算

2010-03-22 21:06:35

2019-03-11 08:00:00

區(qū)塊鏈區(qū)塊鏈技術(shù)管理網(wǎng)絡(luò)

2015-10-22 13:40:53

番茄工作法時(shí)間管理GTD

2012-04-23 15:01:19

2020-06-03 09:00:20

firewall-cm網(wǎng)絡(luò)服務(wù)系統(tǒng)運(yùn)維

2023-01-31 17:36:22

IPLinux網(wǎng)絡(luò)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)