<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          前端部署真的不簡(jiǎn)單

          共 3908字,需瀏覽 8分鐘

           ·

          2024-04-11 08:58

                
                  

          現(xiàn)在大部分的中小型公司部署前端代碼都是比較簡(jiǎn)單的,主要步驟如下:

          首先,通過(guò)腳手架提供的命令npm run build打包前端代碼,生成dist文件夾;

          最后,將dist文件夾丟給后臺(tái)開(kāi)發(fā)人員放在他們的工程里面,隨后臺(tái)一起部署;現(xiàn)在普遍是前后端分開(kāi)部署,因此,利用nginx起一個(gè)web服務(wù)器,將dist文件夾放到指定的路徑下,配置下nginx訪問(wèn)路徑,對(duì)于請(qǐng)求接口使用proxy_pass進(jìn)行轉(zhuǎn)發(fā),解決跨域的問(wèn)題。

          更加高端一點(diǎn)的操作,是利用CI/CD + Docker進(jìn)行自動(dòng)化部署。

          但是,你是否真的想過(guò)前端部署真的就這么簡(jiǎn)單嗎?

          這其實(shí)是一個(gè)非常嚴(yán)肅且復(fù)雜的問(wèn)題,因?yàn)檫@關(guān)系到線上生產(chǎn)環(huán)境的穩(wěn)定。

          有一天,從自知乎上看到一篇張?jiān)讫埓罄性?014年寫(xiě)的文章,非常有啟發(fā),即使這篇文章距離現(xiàn)在有快10年了,但是其中的思想仍然熠熠生輝。

          因?yàn)閷?xiě)的真的是太好了,為了讓更多的人看到,所以大部分內(nèi)容直接就照搬過(guò)來(lái),為了讓自己加深印象。如果想看原文,原文網(wǎng)址[1]在這里。

          那讓我們從原始的前端開(kāi)發(fā)講起。

          下圖是一個(gè) index.html 頁(yè)面和它的樣式文件 a.css,無(wú)需編譯,本地預(yù)覽,丟到服務(wù)器,等待用戶訪問(wèn)。

          c086d8ba2e7597c1eedd8634d37acc4f.webpimage.png

          哇,前端這么簡(jiǎn)單,門檻好低啊。這也是前端有太多人涌入進(jìn)來(lái)的原因。

          接著,我們?cè)L問(wèn)頁(yè)面,看到效果,再查看一下網(wǎng)絡(luò)請(qǐng)求,200!不錯(cuò),太完美了!

          9fd42157ba8f5dcd6137fcde3b382207.webpimage.png

          那么,研發(fā)完成。。。。了么?

          等等,這還沒(méi)完呢!

          對(duì)于像 BAT 這種公司來(lái)說(shuō),那些變態(tài)的訪問(wèn)量和性能指標(biāo),將會(huì)讓前端一點(diǎn)也不好玩。

          看看那個(gè) a.css 的請(qǐng)求,如果每次用戶訪問(wèn)頁(yè)面都要加載,是不是很影響性能,很浪費(fèi)帶寬啊,我們希望最好這樣:

          80fabd8c0b8e6ebc9fbfd89a7b2cf6e7.webpimage.png

          利用304,讓瀏覽器使用本地緩存。

          但,這樣也就夠了嗎?

          不夠!

          304叫協(xié)商緩存,這玩意還是要和服務(wù)器通信一次,我們的優(yōu)化級(jí)別是變態(tài)級(jí),所以必須徹底滅掉這個(gè)請(qǐng)求,要變成這樣:

          c2b7c4ab8209c34ead9f822060e217b5.webpimage.png

          強(qiáng)制瀏覽器使用本地緩存(cache-control/expires),不要和服務(wù)器通信。

          好了,請(qǐng)求方面的優(yōu)化已經(jīng)達(dá)到變態(tài)級(jí)別,那問(wèn)題來(lái)了:你都不讓瀏覽器發(fā)資源請(qǐng)求了,這緩存咋更新

          很好,相信有人想到了辦法:通過(guò)更新頁(yè)面中引用的資源路徑,讓瀏覽器主動(dòng)放棄緩存,加載新資源

          像這樣:

          01b2de8148ac08237dbaf050bd19e0f1.webpimage.png

          下次上線,把鏈接地址改成新的版本,這就更新資源了。

          問(wèn)題解決了么?當(dāng)然沒(méi)有,思考這種情況:

          dd4472edf7c964394a47a8c45756e06b.webpimage.png

          頁(yè)面引用了3個(gè) css 文件,而某次上線只改了其中的a.css,如果所有鏈接都更新版本,就會(huì)導(dǎo)致b.css,c.css的緩存也失效,那豈不是又有浪費(fèi)了?

          不難發(fā)現(xiàn),要解決這種問(wèn)題,必須讓url的修改與文件內(nèi)容關(guān)聯(lián),也就是說(shuō),只有文件內(nèi)容變化,才會(huì)導(dǎo)致相應(yīng)url的變更,從而實(shí)現(xiàn)文件級(jí)別的精確緩存控制

          什么東西與文件內(nèi)容相關(guān)呢?

          我們會(huì)很自然的聯(lián)想到利用數(shù)據(jù)摘要要算法對(duì)文件求摘要信息,摘要信息與文件內(nèi)容一一對(duì)應(yīng),就有了一種可以精確到單個(gè)文件粒度的緩存控制依據(jù)了。

          OK,那我們把 url 改成帶摘要信息的:

          61e119e11574074b45315df06545d6d7.webpimage.png

          這回再有文件修改,就只更新那個(gè)文件對(duì)應(yīng)的 url 了,想到這里貌似很完美了。你覺(jué)得這就夠了么?

          圖樣圖森破!

          現(xiàn)代互聯(lián)網(wǎng)企業(yè),為了進(jìn)一步提升網(wǎng)站性能,會(huì)把靜態(tài)資源和動(dòng)態(tài)網(wǎng)頁(yè)分集群部署,靜態(tài)資源會(huì)被部署到CDN節(jié)點(diǎn)上,網(wǎng)頁(yè)中引用的資源也會(huì)變成對(duì)應(yīng)的部署路徑:

          ae73d869bfee47c056de93bbe9b808a1.webpimage.png

          好了,當(dāng)我要更新靜態(tài)資源的時(shí)候,同時(shí)也會(huì)更新 html 中的引用吧,就好像這樣:

          6dc6dcdb761d1bfbbb5de376b1f48e56.webpimage.png

          這次發(fā)布,同時(shí)改了頁(yè)面結(jié)構(gòu)和樣式,也更新了靜態(tài)資源對(duì)應(yīng)的url地址?,F(xiàn)在重點(diǎn)來(lái)了,現(xiàn)在要發(fā)布代碼上線,親愛(ài)的前端研發(fā)同學(xué),你來(lái)告訴我,咱們是先上線頁(yè)面,還是先上線靜態(tài)資源

          這里的靜態(tài)資源不僅僅包括css文件,也包括圖片,以及不怎么經(jīng)常變的資源。

          1. 先部署動(dòng)態(tài)頁(yè)面,再部署靜態(tài)資源:在二者部署的時(shí)間間隔內(nèi),如果有用戶訪問(wèn)頁(yè)面,就會(huì)在新的頁(yè)面結(jié)構(gòu)中加載舊的資源,并且把這個(gè)舊版本的資源當(dāng)做新版本緩存起來(lái),其結(jié)果就是:用戶訪問(wèn)到了一個(gè)樣式錯(cuò)亂的頁(yè)面,除非手動(dòng)刷新,否則在資源緩存過(guò)期之前,頁(yè)面會(huì)一直執(zhí)行錯(cuò)誤。

          2. 先部署靜態(tài)資源,再部署動(dòng)態(tài)頁(yè)面:在部署時(shí)間間隔之內(nèi),有舊版本資源本地緩存的用戶訪問(wèn)網(wǎng)站,由于請(qǐng)求的頁(yè)面是舊版本的,資源引用沒(méi)有改變,瀏覽器將直接使用本地緩存,這種情況下頁(yè)面展現(xiàn)正常;但沒(méi)有本地緩存或者緩存過(guò)期的用戶訪問(wèn)網(wǎng)站,就會(huì)出現(xiàn)舊版本頁(yè)面加載新版本資源的情況,導(dǎo)致頁(yè)面執(zhí)行錯(cuò)誤,但當(dāng)頁(yè)面完成部署,這部分用戶再次訪問(wèn)頁(yè)面又會(huì)恢復(fù)正常了。

          好的,上面一坨分析想說(shuō)的就是:先部署誰(shuí)都不成!都會(huì)導(dǎo)致部署過(guò)程中發(fā)生頁(yè)面錯(cuò)亂的問(wèn)題。

          所以,訪問(wèn)量不大的項(xiàng)目,可以讓研發(fā)同學(xué)苦逼一把,等到半夜偷偷上線,先上靜態(tài)資源,再部署頁(yè)面,看起來(lái)問(wèn)題少一些。這也是很多公司的部署方案。

          但是,大公司超變態(tài),沒(méi)有這樣的絕對(duì)低峰期,只有相對(duì)低峰期。

          所以,為了穩(wěn)定的服務(wù),還得繼續(xù)追求極致啊!

          這個(gè)奇葩問(wèn)題,起源于資源的 覆蓋式發(fā)布,用待發(fā)布資源覆蓋已發(fā)布資源,就有這種問(wèn)題。

          解決它也好辦,就是實(shí)現(xiàn) 非覆蓋式發(fā)布。

          f91cce466359eea5f2cb9400372904fe.webpimage.png

          看上圖,用文件的摘要信息來(lái)對(duì)資源文件進(jìn)行重命名,把摘要信息放到資源文件發(fā)布路徑中,這樣,內(nèi)容有修改的資源就變成了一個(gè)新的文件發(fā)布到線上,不會(huì)覆蓋已有的資源文件。上線過(guò)程中,先全量部署靜態(tài)資源,再灰度部署頁(yè)面,整個(gè)問(wèn)題就比較完美的解決了。

          因?yàn)楹芏嗲岸碎_(kāi)發(fā)同學(xué)不怎么接觸部署,對(duì)灰度部署不太熟悉,下面將介紹下什么是灰度部署。

          軟件開(kāi)發(fā)一般都是一個(gè)版本一個(gè)版本的迭代。新版本上線前都會(huì)經(jīng)過(guò)測(cè)試,但就算這樣,也不能保證上線了不出問(wèn)題。

          所以,在公司里上線新版本代碼一般都是通過(guò)灰度系統(tǒng)?;叶认到y(tǒng)可以把流量劃分成多份,一份走新版本代碼,一份走老版本代碼。

          bd1405360afabf40696bcf8395a9a6bb.webpimage.png

          而且灰度系統(tǒng)支持設(shè)置流量的比例,比如可以把走新版本代碼的流程設(shè)置為 5%,沒(méi)啥問(wèn)題了再放到 10%,50%,最后放到 100% 全量。這樣可以把出現(xiàn)問(wèn)題的影響降到最低。

          不然一上來(lái)就全量,萬(wàn)一出了線上問(wèn)題,那就是大事故。

          另外,灰度系統(tǒng)不止這一個(gè)用途,比如,產(chǎn)品不確定某些改動(dòng)是不是有效的,就要做 AB 實(shí)驗(yàn),也就是要把流量分成兩份,一份走 A 版本代碼,一份走 B 版本代碼。

          那這樣的灰度系統(tǒng)是怎么實(shí)現(xiàn)的呢?其實(shí)很多都是用 nginx 實(shí)現(xiàn)的。

          nginx 是一個(gè)反向代理的服務(wù),用戶請(qǐng)求發(fā)給它,由它轉(zhuǎn)發(fā)給具體的應(yīng)用服務(wù)器。

          b9119cdf0683a9a0f1c5fb661dddd21d.webpimage.png

          它的過(guò)程如下圖所示:

          e7c011e667ff64c9149deb5ada39ddd8.webpimage.png

          首先,需要對(duì)流量進(jìn)行染色,即對(duì)這個(gè)用戶進(jìn)行標(biāo)注,讓這個(gè)用戶訪問(wèn)服務(wù)1,另外的用戶訪問(wèn)服務(wù)2。染色的方式有很多,可以通過(guò)cookie來(lái)完成。不同的用戶攜帶的cookie是不同的。第一染色的時(shí)候,所有的用戶都訪問(wèn)服務(wù)1。

          然后,第二次訪問(wèn)的時(shí)候,nginx根據(jù)用戶攜帶的cookie進(jìn)行轉(zhuǎn)發(fā)到不同的服務(wù),這樣就完成了灰度訪問(wèn)。

          好了,灰度部署就介紹到這里,回到原文講的先全量部署靜態(tài)資源,再灰度部署頁(yè)面,這是什么意思呢?

          首先,部署靜態(tài)資源的時(shí)候,不要?jiǎng)h除原來(lái)的靜態(tài)資源,而是把新的靜態(tài)資源發(fā)復(fù)制過(guò)去,因?yàn)槲募谜惴ㄖ孛?,所以不?huì)發(fā)生重名的問(wèn)題。

          其次,灰度部署動(dòng)態(tài)頁(yè)面,也就是一部分用戶訪問(wèn)老的頁(yè)面,一部分用戶訪問(wèn)新的頁(yè)面。訪問(wèn)老頁(yè)面的用戶請(qǐng)求的還是老資源,直接使用緩存。訪問(wèn)新頁(yè)面的用戶訪問(wèn)新資源,此時(shí)新資源已經(jīng)部署完成,所以不會(huì)訪問(wèn)老的資源,導(dǎo)致頁(yè)面出現(xiàn)錯(cuò)誤。

          最后,根據(jù)訪問(wèn)情況,利用灰度系統(tǒng),逐漸把訪問(wèn)老頁(yè)面的用戶過(guò)渡到訪問(wèn)新頁(yè)面上。

          所以,大公司的靜態(tài)資源優(yōu)化方案,基本上要實(shí)現(xiàn)這么幾個(gè)東西:

          1. 配置超長(zhǎng)時(shí)間的本地緩存:節(jié)省帶寬,提高性能

          2. 采用內(nèi)容摘要作為緩存更新依據(jù):精確的緩存控制

          3. 靜態(tài)資源CDN部署:優(yōu)化網(wǎng)絡(luò)請(qǐng)求

          4. 更資源發(fā)布路徑實(shí)現(xiàn)非覆蓋式發(fā)布:平滑升級(jí)

          全套做下來(lái),就是相對(duì)比較完整的靜態(tài)資源緩存控制方案了,而且,還要注意的是,靜態(tài)資源的緩存控制要求在前端所有靜態(tài)資源加載的位置都要做這樣的處理

          是的,所有!

          什么js、css自不必說(shuō),還要包括js、css文件中引用的資源路徑,由于涉及到摘要信息,引用資源的摘要信息也會(huì)引起引用文件本身的內(nèi)容改變,從而形成級(jí)聯(lián)的摘要變化,大概就是:

          2844a211f3263f2ff3b29bae25d341a4.webpimage.png

          到這里本文結(jié)束了,我們已經(jīng)了解了前端部署中關(guān)于靜態(tài)資源緩存要面臨的優(yōu)化和部署問(wèn)題,新的問(wèn)題又來(lái)了:這?讓工程師怎么寫(xiě)碼啊?。?!

          這又會(huì)扯出一堆有關(guān)模塊化開(kāi)發(fā)、資源加載、請(qǐng)求合并、前端框架等等的工程問(wèn)題。

          媽媽,我再也不玩前端了。。。。

          原文: https://juejin.cn/post/7316202725330796571 作者:小p 參考資料

          [1]

          https://www.zhihu.com/question/20790576

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩欧美高清无码 | 婷婷精品AV | 成人毛片18女人免费看 | 伊人成年网站综合网 | 免费干屄视频 |