
我們知道,用戶體驗是 Web 產品最為重要的部分,盡可能減少首屏加載時間,更為流暢地展示用戶所需求的內容,會是用戶是否留存的關鍵因素,
而隨著現代 Web 業務可供用戶的互動行為越來越多,前端專案的復雜度越來越高,每個頁面的渲染時間也必然越來越長,這就導致了用戶的體驗不佳,用戶的操作變慢,
為此,前端工程師們在首屏請求的各個階段中持續鉆研,不斷探究如何將首次頁面渲染的時間減少到更小,力求提供更為優秀的產品體驗,
CSR(Client Side Render)

瀏覽器渲染是最簡單,最符合 Web 應用設計思路的渲染方式,
所謂瀏覽器渲染,就是將應用所需的頁面展示、前端邏輯、介面請求全都在用戶的瀏覽器中執行,它很好的實作了前后端的解耦,讓前端開發更為獨立,也讓后臺實作更為簡單,
同時,為了緩解用戶的等待焦慮,我們可以用 loading 態,或者骨架屏,進一步提升異步請求介面時的用戶體驗,
不過,隨著業務復雜程度提高,瀏覽器渲染的開銷也會變大,我們無法控制用戶側使用的機器性能,很多時候,用戶使用的機器性能甚至不足以滿足應用的需求,造成卡頓,甚至崩潰,這一點在移動端上尤甚,
而瀏覽器渲染由于前端的動態性過高,也會帶來 SEO 不佳的問題,
SSR(Server Side Render)

服務端渲染的出現時間實際上是要比瀏覽器渲染要更早的,在 Web 應用發展的早期,所有的 ASP、JSP 等模板引擎構建的前端頁面實際上就是服務端渲染的結果,而此時的服務端渲染無法進行前后端職責的解耦,因此逐步被瀏覽器渲染淘汰,
但在處理首屏體驗的問題上,服務端渲染有著獨到的優勢,它能提前再服務端中完成頁面模板的資料填充,從而一次性回傳完整的首屏內容,從而面對 SEO 的爬取時能獲取到更多有效的關鍵資訊,
此外,由于其能快速直出首頁的真實資料,體驗往往比 loading 態更佳,在 TTI 的表現上更為出色,
但是,服務端渲染也有其自身的局限性,因為從本質上來說,SSR 服務無法完全與前端頁面解耦開來,因此市面上較完備的 SSR 解決方案都只解決首屏的服務端渲染,并采用同構的方式,增加一層 node 中間層的方式來解決前端與 SSR 服務的更新同步問題,并與后端開發專案解耦,
但這無疑增加了專案的復雜度,并且隨著業務的復雜程度變高,服務端渲染往往需要調起多個介面去請求資料并填充頁面,這樣可能會導致在 TTFB 上有一定劣勢,
當然,最重要的是,服務端渲染對于服務器的負載要求是很高的,

上圖是參考的位元組的某專案的 SSR 服務的單機 QPS 承載表現,我們可以看出,對于一個高訪問量的網頁應用來說,提供一個較為復雜的 SSR 服務的成本是相當高的,需要花費大量的金錢來堆機器,
因此,從降本增效的角度考慮,我們需要評估 SSR 帶來的 ROI 是否符合預期,
NSR(Native Side Render)
在移動互聯網的浪潮下,移動端機能飛速提升,那么 Web 應用是否能搭上這一班車,將 Native 的性能利用起來,提升頁面渲染性能呢?答案是肯定的,這就需要介紹到 NSR 了,

Native 渲染的本質其實還是 SSR,只不過提供服務的 Server 轉變為了客戶端,由于需要用到客戶端機能,因此此種實作通常應用在移動端 APP,或者 PWA 下,
當鏈接被點擊時,先借助瀏覽器啟用一個 JS 運行時,并加載 APP 中存盤的 Html 模板,發送 xhr 請求預加載頁面資料,從而在客戶端本地拼接并渲染生成一個有資料的 Html 首屏,形成首次 NSR,同時可以將該首屏 Html 快取在客戶端,供下次頁面打開時,實作 stale-while-revalidate 的快取效果,
由于 NSR 將服務器的渲染作業放在了客戶端的一個個獨立設備中,既實作了頁面的預加載,同時又不會增加額外的服務器壓力,達到秒看的效果,
這種能力在擁有客戶端或者支持 PWA 的應用中應用廣泛,例如手 Q,騰訊檔案 APP 中都擁有通過 APP 中的離線包來實作首屏渲染加速的能力,
ESR(Edge Side Render)
那么,對于純 Web 應用,而又由于兼容性等原因暫時無法支持 PWA 的頁面,有沒有一個合適的首屏渲染加速方案呢?
隨著云與邊緣計算的快速發展,前端頁面也需要考慮分布式的請求處理優化,

我們知道,CDN 節點相比真實服務節點更貼近用戶,能更快將內容回傳,因此我們可以將靜態的 Html 內容模板快取在 CDN 上,當接到請求時,先快速將靜態模板頁面回傳給用戶,同時在 CDN 服務器上對頁面動態部分發起向后端發起請求,并將獲取到的動態內容在以流式下發的方式繼續回傳給用戶,
這里實際上利用到了 HTTP 的 SSE(Server Send Events)協議,通過服務器向客戶端發送單向事件流,實作同一個 Html 檔案的分塊傳輸預渲染,
最佳實踐是?
這也是我們最近在騰訊檔案中探索實踐并落地的,通過服務中間節點的流式下發能力,實作多級首屏渲染加速,
對于一個復雜前端頁面來說,首屏需要加載和運算的資源型別可能有很多,有需要客戶端決議并執行的 JS 動效,也有需要服務端獲取資料直出的資料分片展示頁面,
通常來說,客戶端只能等待服務端獲取分片資料,并生成經過 SSR 渲染后的 HTML,才能開始進行 script 決議與 js 資源拉取的行為,最終渲染出完整的頁面資料以及動效,
而既然他們所需要的計算方式不同,那么為什么不能并行來做呢?
我們可以在版本發布前,將未經過服務端直出的模板 HTML 進行決議,將需要發起資源請求的所有的外鏈腳本 url 提取出來,生成一個 HTML Header 結構,并將該 Header 內容偽裝為正常 HTML 快取在 CDN 節點中,
結合之前我們介紹的 HTTP SSE 協議,當用戶請求時,我們可以以最快的速度向用戶回傳 CDN 中的 HTML header,從而讓用戶的瀏覽器提前拉取并決議外鏈資源,于此同時,CDN 節點將用戶的請求轉發給真實的服務端,從而讓服務端進行真實資料的獲取拼接并回傳給客戶端,
由于客戶端此時已經提前拉取了外鏈資源,因此收到服務端分片的 SSR 后,客戶端可以直接將真實資料渲染到頁面中,而不需要再次等待外鏈資源的決議,
由于并行的關系,這樣的 SSR 與 NSR 混合方式能大大降低復雜頁面首屏渲染的時間,提升用戶體驗,
以百度首頁的請求為例,通過 Chorme Network 提供的瀑布圖,通過我們可以直觀的看到一條請求的執行程序,

我們可以看出,除了 DNS 尋址與 SSL 建連是我們無法控制的以外,占用請求時間的大頭是 Waiting for server response,請求服務器 (CDN) 的時間,以及 Content Download,外鏈資源的拉取時間,
而使用本文的混合方案后,理論上可以使總請求時間降低到 Max(A, B), (A 為 Waiting for server response,B 為 Content Download) 的水平,(當然,實際操作程序中,由于 CDN 節點進行了一次請求轉發,因此擁有 SSR 能力的頁面請求回傳時間會更長一些),
結語
前端的頁面首屏時間優化是永恒的話題,本文介紹了前端界對首屏時間優化的行程,并提供了一種 SSR 與 NSR 混合的新思路,通過并行處理耗時任務的方式,進一步提升首屏加載時間,希望能夠給大家提供一點參考價值,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/517652.html
標籤:其他
