大公司里怎樣開發(fā)和部署前端代碼肥惭?(附實踐方案)

像往常瀏覽各大學習網(wǎng)站一樣,今天突然看到別人在知乎上提的一個問題:大公司里怎樣開發(fā)和部署前端代碼紊搪?
以前就關(guān)注過這個問題蜜葱,今天重新看到就多查了點資料。下面耀石,貼出我在網(wǎng)上看到的 張云龍(@前端農(nóng)民工) 寫的文章牵囤。并且,我會在最后附上我本地實踐的例子滞伟。


下面是原文:

這是一個非常有趣的 非主流前端領(lǐng)域揭鳞,這個領(lǐng)域要探索的是如何用工程手段解決前端開發(fā)和部署優(yōu)化的綜合問題,入行到現(xiàn)在一直在學習和實踐中诗良。
在我的印象中汹桦,facebook是這個領(lǐng)域的鼻祖,有興趣鉴裹、有梯子的同學可以去看看facebook的頁面源代碼舞骆,體會一下什么叫工程化。
接下來径荔,我想從原理展開講述督禽,多圖,較長总处,希望能有耐心看完狈惫。


讓我們返璞歸真,從原始的前端開發(fā)講起鹦马。上圖是一個“可愛”的index.html頁面和它的樣式文件a.css胧谈,用文本編輯器寫代碼忆肾,無需編譯,本地預(yù)覽菱肖,確認OK客冈,丟到服務(wù)器,等待用戶訪問稳强。前端就是這么簡單场仲,好好玩啊,門檻好低啊退疫,分分鐘學會有木有渠缕!

然后我們訪問頁面,看到效果褒繁,再查看一下網(wǎng)絡(luò)請求亦鳞,200!不錯澜汤,太?完美了蚜迅!那么板丽,研發(fā)完成铜跑。臀叙。。徽诲。了么?
等等吵血,這還沒完呢谎替!對于大公司來說,那些變態(tài)的訪問量和性能指標蹋辅,將會讓前端一點也不“好玩”钱贯。
看看那個a.css的請求吧,如果每次用戶訪問頁面都要加載侦另,是不是很影響性能秩命,很浪費帶寬啊,我們希望最好這樣:

利用304褒傅,讓瀏覽器使用本地緩存弃锐。但,這樣也就夠了嗎殿托?不成霹菊!304叫協(xié)商緩存,這玩意還是要和服務(wù)器通信一次支竹,我們的優(yōu)化級別是變態(tài)級旋廷,所以必須徹底滅掉這個請求鸠按,變成這樣:

強制瀏覽器使用本地緩存(cache-control/expires),不要和服務(wù)器通信饶碘。好了待诅,請求方面的優(yōu)化已經(jīng)達到變態(tài)級別,那問題來了:你都不讓瀏覽器發(fā)資源請求了熊镣,這緩存咋更新卑雁?
很好,相信有人想到了辦法:通過更新頁面中引用的資源路徑绪囱,讓瀏覽器主動放棄緩存测蹲,加載新資源。好像這樣:

下次上線鬼吵,把鏈接地址改成新的版本扣甲,就更新資源了不是。OK齿椅,問題解決了么琉挖?!當然沒有涣脚!大公司的變態(tài)又來了示辈,思考這種情況:

頁面引用了3個css,而某次上線只改了其中的a.css遣蚀,如果所有鏈接都更新版本矾麻,就會導(dǎo)致b.css,c.css的緩存也失效芭梯,那豈不是又有浪費了险耀?!
重新開啟變態(tài)模式玖喘,我們不難發(fā)現(xiàn)甩牺,要解決這種問題,必須讓url的修改與文件內(nèi)容關(guān)聯(lián)累奈,也就是說贬派,只有文件內(nèi)容變化,才會導(dǎo)致相應(yīng)url的變更费尽,從而實現(xiàn)文件級別的精確緩存控制赠群。
什么東西與文件內(nèi)容相關(guān)呢?我們會很自然的聯(lián)想到利用 數(shù)據(jù)摘要要算法 對文件求摘要信息旱幼,摘要信息與文件內(nèi)容一一對應(yīng)查描,就有了一種可以精確到單個文件粒度的緩存控制依據(jù)了。好了,我們把url改成帶摘要信息的:

這回再有文件修改冬三,就只更新那個文件對應(yīng)的url了匀油,想到這里貌似很完美了。你覺得這就夠了么勾笆?大公司告訴你:圖樣圖森破敌蚜!
唉~~~~,讓我喘口氣
現(xiàn)代互聯(lián)網(wǎng)企業(yè)窝爪,為了進一步提升網(wǎng)站性能弛车,會把靜態(tài)資源和動態(tài)網(wǎng)頁分集群部署,靜態(tài)資源會被部署到CDN節(jié)點上蒲每,網(wǎng)頁中引用的資源也會變成對應(yīng)的部署路徑:

好了纷跛,當我要更新靜態(tài)資源的時候,同時也會更新html中的引用吧邀杏,就好像這樣:

這次發(fā)布贫奠,同時改了頁面結(jié)構(gòu)和樣式,也更新了靜態(tài)資源對應(yīng)的url地址望蜡,現(xiàn)在要發(fā)布代碼上線唤崭,親愛的前端研發(fā)同學,你來告訴我脖律,咱們是先上線頁面谢肾,還是先上線靜態(tài)資源?

先部署頁面状您,再部署資源:

在二者部署的時間間隔內(nèi)勒叠,如果有用戶訪問頁面,就會在新的頁面結(jié)構(gòu)中加載舊的資源膏孟,并且把這個舊版本的資源當做新版本緩存起來,其結(jié)果就是:用戶訪問到了一個樣式錯亂的頁面拌汇,除非手動刷新柒桑,否則在資源緩存過期之前,頁面會一直執(zhí)行錯誤噪舀。

先部署資源魁淳,再部署頁面:

在部署時間間隔之內(nèi),有舊版本資源本地緩存的用戶訪問網(wǎng)站与倡,由于請求的頁面是舊版本的界逛,資源引用沒有改變,瀏覽器將直接使用本地緩存纺座,這種情況下頁面展現(xiàn)正常息拜;但沒有本地緩存或者緩存過期的用戶訪問網(wǎng)站,就會出現(xiàn)舊版本頁面加載新版本資源的情況,導(dǎo)致頁面執(zhí)行錯誤少欺,但當頁面完成部署喳瓣,這部分用戶再次訪問頁面又會恢復(fù)正常了。 好的赞别,上面一坨分析想說的就是:先部署誰都不成畏陕!都會導(dǎo)致部署過程中發(fā)生頁面錯亂的問題。所以仿滔,訪問量不大的項目惠毁,可以讓研發(fā)同學苦逼一把,等到半夜偷偷上線崎页,先上靜態(tài)資源仁讨,再部署頁面,看起來問題少一些实昨。

但是洞豁,大公司超變態(tài),沒有這樣的“絕對低峰期”荒给,只有“相對低峰期”丈挟。So,為了穩(wěn)定的服務(wù)志电,還得繼續(xù)追求極致笆镅省!
這個奇葩問題挑辆,起源于資源的 覆蓋式發(fā)布例朱,用 待發(fā)布資源 覆蓋 已發(fā)布資源,就有這種問題鱼蝉。解決它也好辦洒嗤,就是實現(xiàn) 非覆蓋式發(fā)布。



看上圖魁亦,用文件的摘要信息來對資源文件進行重命名渔隶,把摘要信息放到資源文件發(fā)布路徑中,這樣洁奈,內(nèi)容有修改的資源就變成了一個新的文件發(fā)布到線上间唉,不會覆蓋已有的資源文件。上線過程中利术,先全量部署靜態(tài)資源呈野,再灰度部署頁面,整個問題就比較完美的解決了印叁。
所以被冒,大公司的靜態(tài)資源優(yōu)化方案军掂,基本上要實現(xiàn)這么幾個東西:
配置超長時間的本地緩存 —— 節(jié)省帶寬,提高性能
采用內(nèi)容摘要作為緩存更新依據(jù) —— 精確的緩存控制
靜態(tài)資源CDN部署 —— 優(yōu)化網(wǎng)絡(luò)請求
更資源發(fā)布路徑實現(xiàn)非覆蓋式發(fā)布 —— 平滑升級

全套做下來姆打,就是相對比較完整的靜態(tài)資源緩存控制方案了良姆,而且,還要注意的是幔戏,靜態(tài)資源的緩存控制要求在 前端所有靜態(tài)資源加載的位置都要做這樣的處理 玛追。是的,所有闲延!什么js痊剖、css自不必說,還要包括js垒玲、css文件中引用的資源路徑陆馁,由于涉及到摘要信息,引用資源的摘要信息也會引起引用文件本身的內(nèi)容改變合愈,從而形成級聯(lián)的摘要變化叮贩,大概示意圖就是:


好了,目前我們快速的學習了一下前端工程中關(guān)于靜態(tài)資源緩存要面臨的優(yōu)化和部署問題佛析,新的問題又來了:這?讓工程師怎么寫碼耙胬稀!4缒捺萌!
要解釋優(yōu)化與工程的結(jié)合處理思路,又會扯出一堆有關(guān)模塊化開發(fā)膘茎、資源加載桃纯、請求合并、前端框架等等的工程問題披坏,以上只是開了個頭态坦,解決方案才是精髓,但要說的太多太多刮萌,有空再慢慢展開吧驮配。
總之,前端性能優(yōu)化絕逼是一個工程問題着茸!

以上不是我YY的,可以觀察 百度 或者 facebook 的頁面以及靜態(tài)資源源代碼琐旁,查看它們的資源引用路徑處理涮阔,以及網(wǎng)絡(luò)請中靜態(tài)資源的緩存控制部分。再次贊嘆facebook的前端工程建設(shè)水平灰殴,跪舔了敬特。
建議前端工程師多多關(guān)注前端工程領(lǐng)域掰邢,也許有人會覺得自己的產(chǎn)品很小,不用這么變態(tài)伟阔,但很有可能說不定某天你就需要做出這樣的改變了辣之。而且,如果我們能把事情做得更極致皱炉,為什么不去做呢怀估?
另外,也不要覺得這些是運維或者后端工程師要解決的問題合搅。如果由其他角色來解決多搀,大家總是把自己不關(guān)心的問題丟給別人,那么前端工程師的開發(fā)過程將受到極大的限制灾部,這種情況甚至在某些大公司都不少見康铭!
媽媽,我再也不玩前端了赌髓。从藤。。锁蠕。5555
業(yè)界實踐
Assets Pipeline
Rails中的Assets Pipeline完成了以上所說的優(yōu)化細節(jié)夷野,對整個靜態(tài)資源的管理上的設(shè)計思考也是如此,了解rails的人也可以把此答案當做是對rails中assets pipeline設(shè)計原理的分析匿沛。
rails通過把靜態(tài)資源變成erb模板文件扫责,然后加入<%= asset_path ‘image.png’ %>,上線前預(yù)編譯完成處理逃呼,fis的實現(xiàn)思路跟這個幾乎完全一樣鳖孤,但我們當初確實不知道有rails的這套方案存在。
相關(guān)資料:
英文版:http://guides.rubyonrails.org/asset_pipeline.html
中文版:http://guides.ruby-china.org/asset_pipeline.html

FIS的解決方案
用 F.I.S 包裝了一個小工具抡笼,完整實現(xiàn)整個回答所說的最佳部署方案苏揣,并提供了源碼對照,可以感受一下項目源碼和部署代碼的對照推姻。
源碼項目:https://github.com/fouber/static-resource-digest-project
部署項目:https://github.com/fouber/static-resource-digest-project-release

部署項目可以理解為線上發(fā)布后的結(jié)果平匈,可以在部署項目里查看所有資源引用的md5化處理。
這個示例也可以用于和assets pipeline做比較藏古。fis沒有assets的目錄規(guī)范約束增炭,而且可以以獨立工具的方式組合各種前端開發(fā)語言(coffee、less拧晕、sass/scss隙姿、stylus、markdown厂捞、jade输玷、ejs队丝、handlebars等等你能想到的),并與其他后端開發(fā)語言結(jié)合欲鹏。
assets pipeline的設(shè)計思想值得獨立成工具用于前端工程机久,fis就當做這樣的一個選擇吧。

本地實踐

按照上文提到的FIS的解決方案赔嚎,我本地嘗試了一下膘盖,確實使用起來非常快捷尽狠。```

- 隨便準備一個項目(附我自己新建的測試項目)
  項目結(jié)構(gòu):
![屏幕快照 2016-07-08 13.17.04.png](http://upload-images.jianshu.io/upload_images/712523-c8cb15c5860e9a34.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
 index.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<h1>Test</h1>
<img src="./images/test.jpg" alt="pic test" class="img">
<ul class="js-ul">
<li class="dn js-li"></li>
</ul>
<script src="./js/jquery-1.12.0.min.js"></script>
<script src="./js/index.js"></script>
</body>
</html>


  index.js:

$(function(){

//數(shù)據(jù)源
var data = ["hello A","hello B","hello C"];

//構(gòu)造列表
var $nodeArray = [];
$.each(data,function(index,item){
    var $node = $(".js-li").clone().removeClass("dn");
    $node.html(item);
    $nodeArray.push($node[0].outerHTML);
});

//綁定頁面
$(".js-ul").html($nodeArray.join(""));

});


- 配置環(huán)境:

1.安裝nodejs
2.npm install -g rsd


- 打包部署項目

1.命令行通過cd命令進入項目所在根目錄
2.在項目根目錄下創(chuàng)建一個空的 fis-conf.js文件
3.命令行中執(zhí)行 rsd release --md5 --dest ../output
(PS:../output是最終打包生成的文件所在的目錄衔憨,可以自己隨意指定)

- 打包效果

按照上面的步驟,就可以得到最終生成的文件袄膏,現(xiàn)在再來看看項目結(jié)構(gòu)以及index.html代碼


![屏幕快照 2016-07-08 13.25.32.png](http://upload-images.jianshu.io/upload_images/712523-dcec5da7ad510eac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="/css/index_fd3dde4.css">
</head>
<body>
<h1>Test</h1>
<img src="/images/test_24c18dd.jpg" alt="pic test" class="img">
<ul class="js-ul">
<li class="dn js-li"></li>
</ul>
<script src="/js/jquery-1.12.0.min_cbb11b5.js"></script>
<script src="/js/index_62d2fd0.js"></script>
</body>
</html>

#####你看文件名和資源引用的名稱都變化了践图,是不是很簡單〕凉荩快動手去嘗試吧~~
<br>
參考文章:[大公司里怎樣開發(fā)和部署前端代碼码党?](http://web.jobbole.com/83392/)    [FIS解決方案](https://github.com/fouber/static-resource-digest-project)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市斥黑,隨后出現(xiàn)的幾起案子揖盘,更是在濱河造成了極大的恐慌,老刑警劉巖锌奴,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兽狭,死亡現(xiàn)場離奇詭異,居然都是意外死亡鹿蜀,警方通過查閱死者的電腦和手機箕慧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茴恰,“玉大人颠焦,你說我怎么就攤上這事⊥妫” “怎么了伐庭?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長分冈。 經(jīng)常有香客問我圾另,道長,這世上最難降的妖魔是什么雕沉? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任盯捌,我火速辦了婚禮,結(jié)果婚禮上蘑秽,老公的妹妹穿的比我還像新娘饺著。我一直安慰自己,他們只是感情好肠牲,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布幼衰。 她就那樣靜靜地躺著,像睡著了一般缀雳。 火紅的嫁衣襯著肌膚如雪渡嚣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天肥印,我揣著相機與錄音识椰,去河邊找鬼。 笑死深碱,一個胖子當著我的面吹牛腹鹉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播敷硅,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼功咒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了绞蹦?” 一聲冷哼從身側(cè)響起力奋,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幽七,沒想到半個月后景殷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡澡屡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年猿挚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挪蹭。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡亭饵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出梁厉,到底是詐尸還是另有隱情辜羊,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布词顾,位于F島的核電站八秃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肉盹。R本人自食惡果不足惜昔驱,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望上忍。 院中可真熱鬧骤肛,春花似錦纳本、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至淑玫,卻和暖如春巾腕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背絮蒿。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工尊搬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人土涝。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓佛寿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親回铛。 傳聞我的和親對象是個殘疾皇子狗准,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容