導(dǎo)讀:本文雖然明指了某個主頁有關(guān)web前端網(wǎng)站,但是其實(shí)是適合所有網(wǎng)站系統(tǒng)前端的優(yōu)化技巧的。
最近,我們將 主頁的性能提升了十倍以上。在本文中,我們將解析實(shí)現(xiàn)這一重大改進(jìn)的具體技術(shù)手段。
但在開始之前,讓我們先對網(wǎng)絡(luò)性能的重要意義進(jìn)行一番論證(博文末尾提供相關(guān)案例研究鏈接):
在本篇文章中,我們將簡要介紹以下幾大有助于我們提高頁面性能的主要領(lǐng)域:
這里再介紹一點(diǎn)我們的情況:我們的主頁由 React()、()、( )以及 API(Ruby on Rails)構(gòu)建而成。以下為主頁在移動設(shè)備上顯示的效果:
主頁與瀏覽效果
性能測量
沒有數(shù)據(jù)作為支持,一切意見都將毫無意義。
—— W.
實(shí)驗(yàn)室工具
實(shí)驗(yàn)室工具能夠立足受控環(huán)境從預(yù)定義的設(shè)備及網(wǎng)絡(luò)設(shè)置中收集數(shù)據(jù)。利用這些工具,我們能夠輕松調(diào)試任何性能問題并實(shí)現(xiàn)良好的可重復(fù)測試。
就是一款立足本地計算機(jī)對 內(nèi)網(wǎng)頁進(jìn)行審計的出色工具。其能夠提供一系列關(guān)于如何提高性能、可訪問性以及搜索引擎優(yōu)化的實(shí)用性提示。下面,我們來看模擬高速 3G 加 4x CPU 場景下的 性能審計報告:
之前與之后:首屏內(nèi)容填充(簡稱 FCP)性能實(shí)現(xiàn) 10 倍提升
然而,單純使用實(shí)驗(yàn)室工具也會帶來不少弊端:這類工具不一定能準(zhǔn)確反映出最終用戶所面臨的設(shè)備、網(wǎng)絡(luò)、位置以及多種其它現(xiàn)實(shí)因素造成的性能瓶頸。正因?yàn)槿绱耍覀儾判枰浜犀F(xiàn)場工具進(jìn)行補(bǔ)充。
現(xiàn)場工具
現(xiàn)場工具允許我們模擬并測量用戶的真實(shí)頁面負(fù)載。目前有多種服務(wù)可幫助大家從實(shí)際設(shè)備當(dāng)中獲取真實(shí)性能數(shù)據(jù):
報告
渲染
內(nèi)容的渲染可通過多種方法實(shí)現(xiàn),其中每一種都擁有獨(dú)特的優(yōu)勢與缺點(diǎn):
客戶端渲染
以前,我們將自己的主頁與 Ember.js 框架一同實(shí)現(xiàn)為采用客戶端渲染方法的單頁面應(yīng)用。但這種做法的一大問題在于,我們的 Ember.js 應(yīng)用程序包過大。這意味著在瀏覽器下載 文件并對其進(jìn)行解析、編譯與執(zhí)行的過程中,用戶只能對著空白屏幕發(fā)呆:
最要命的空白屏幕
因此,我們決定利用 React 重構(gòu)應(yīng)用當(dāng)中的某些部分。
預(yù)渲染與服務(wù)器端渲染
客戶端渲染應(yīng)用程序的具體構(gòu)建——例如采用 React DOM,仍然會帶來與 Ember.js 相同的問題。 需要占用大量資源,而且訪問者需要經(jīng)歷一段首屏內(nèi)容填充周期才能看到實(shí)際內(nèi)容。
因此在決定使用 React 之后,我們開始嘗試其它潛在的渲染選項(xiàng),以確保瀏覽器能夠更快地完成內(nèi)容渲染。
使用 React 時的常規(guī)渲染選項(xiàng)
因此,我們打算嘗試一下混合方法,即發(fā)揮每一種渲染選項(xiàng)中的獨(dú)特優(yōu)勢。
運(yùn)行時預(yù)渲染
是一套 Node.js 庫,允許用戶使用 。我們希望嘗試?yán)? 在運(yùn)行時當(dāng)中實(shí)現(xiàn)預(yù)渲染。這代表著一種有趣的混合方法:利用 進(jìn)行服務(wù)器端渲染,同時利用 進(jìn)行客戶端渲染。感興趣的朋友可以點(diǎn)擊此處查看谷歌提供的關(guān)于如何利用 瀏覽器進(jìn)行服務(wù)器端渲染的相關(guān)提示。
利用 對 React 應(yīng)用程序進(jìn)行運(yùn)行時預(yù)渲染
這種方法具備以下優(yōu)勢:
但在采用這種方法的過程中有關(guān)web前端網(wǎng)站,我們也遇到了一些挑戰(zhàn):
利用 的服務(wù)器端渲染架構(gòu)
? 穩(wěn)定性。對眾多 瀏覽器進(jìn)行規(guī)模伸縮,同時保持進(jìn)程不致過熱并實(shí)現(xiàn)負(fù)載均衡絕對是一項(xiàng)高難挑戰(zhàn)。我們嘗試了不同的托管方法,包括在 集群內(nèi)進(jìn)行自托管,以及利用 AWS 與 Cloud 實(shí)現(xiàn)無服務(wù)器計算。我們注意到,后一種方法在配合 時存在一些性能問題:
AWS 和GCP函數(shù)的響應(yīng)時間
在配合 AWS 與 GCP 時, 的響應(yīng)時間結(jié)果隨著我們對 熟悉程度的逐步提升,我們開始對初始方法進(jìn)行迭代(后文將具體說明)。我們還進(jìn)行了其它一系列有趣的實(shí)驗(yàn),希望通過 瀏覽器渲染 PDF。再有,即使不編寫任何代碼,我們也能夠利用 自動進(jìn)行端到端測試。而且除了 之外, 現(xiàn)在還支持 瀏覽器。
混合渲染方法
在運(yùn)行時中使用 并非易事。正因?yàn)槿绱?,我們才決定在構(gòu)建時中加以使用,同時配合一款工具用于在運(yùn)行時內(nèi)從服務(wù)器端獲取用戶生成的實(shí)際內(nèi)容。很明顯,這款工具必須擁有比 更強(qiáng)大的穩(wěn)定性與吞吐能力。
我們決定使用 編程語言。 看起來與 Ruby 非常相似,但運(yùn)行在 BEAM( VM)之上。順帶一提,BEAM 專門為構(gòu)建高容錯、高穩(wěn)定性系統(tǒng)而生。
采用 Actor 并發(fā)模型。每個“Actor”(即 進(jìn)程)的內(nèi)存占用量都非常有限,僅為 1 到 2 KB。這意味著系統(tǒng)將能夠同時運(yùn)行成千上萬個獨(dú)立的進(jìn)程。 則是一套 Web 框架,能夠支持高吞吐量,并允許開發(fā)者在各個獨(dú)立的 進(jìn)程當(dāng)中處理各項(xiàng) HTTP 請求。
我們將上述方法結(jié)合起來,充分利用其各自優(yōu)勢,希望能夠切實(shí)滿足自身需求:
用于實(shí)現(xiàn)預(yù)渲染, 則用于實(shí)現(xiàn)服務(wù)器端渲染
我們可以繼續(xù)構(gòu)建一款簡單的瀏覽器 React 應(yīng)用程序,并在無需等待最終用戶設(shè)備 處理過程的同時獲得快速初始頁面加載效果。
利用 建立預(yù)渲染架構(gòu),利用 進(jìn)行服務(wù)器端渲染,React 則在客戶端上實(shí)現(xiàn)
網(wǎng)絡(luò)內(nèi)容交付網(wǎng)絡(luò) (CDN)
利用 CDN 可幫助我們實(shí)現(xiàn)內(nèi)容緩存,并加速其在全球范圍內(nèi)的交付速度。我們選擇了 ,其目前處理著全球超過 10% 的請求總量,并得到 、、 以及 等諸多廠商的青睞。
允許我們編寫定制化緩存,并可利用 VCL 配置語言建立路由邏輯。下面,我們將具體聊聊基礎(chǔ)請求流如何根據(jù)路由、請求頭等因素分步起效:
VCL 請求流
提高性能的另一個選項(xiàng)是配合 在邊緣位置使用 (WASM)。大家可以將其視為一種無服務(wù)器模式,只是處于邊緣位置;所使用的語言則包括 C、Rust、Go 以及 等等。 就擁有一個類似的項(xiàng)目,用于在 上支持 WASM。
緩存
盡可能多地利用緩存處理請求是改善性能水平的關(guān)鍵所在。立足 CDN 層級進(jìn)行緩存,將能夠更快地為新用戶提供響應(yīng)。而通過發(fā)送 Cache- 頭進(jìn)行緩存,則可加快瀏覽器中重復(fù)請求的響應(yīng)速度。
大多數(shù)構(gòu)建工具(例如 )允許用戶向文件名當(dāng)中添加哈希值。由于指向這些文件的任何變更都會產(chǎn)生新的輸出文件名,因此大家可以安心將文件添加至緩存當(dāng)中。