
現(xiàn)代 Web 業(yè)務(wù)可供用戶的交互行為越來越多,前端項目的復(fù)雜度越來越高,每個頁面的渲染時間也必然越來越長,這就導(dǎo)致了用戶的體驗不佳,用戶的操作變慢。
為此,前端工程師們在首屏請求的各個階段中持續(xù)鉆研,不斷探究如何將首次頁面渲染的時間減少到更小,力求提供更為優(yōu)秀的產(chǎn)品體驗。
CSR(Client Side Render)

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

服務(wù)端渲染的出現(xiàn)時間實際上是要比瀏覽器渲染要更早的。在 Web 應(yīng)用發(fā)展的早期,所有的 ASP、JSP 等模板引擎構(gòu)建的前端頁面實際上就是服務(wù)端渲染的結(jié)果。而此時的服務(wù)端渲染無法進(jìn)行前后端職責(zé)的解耦,因此逐步被瀏覽器渲染淘汰。
但在處理首屏體驗的問題上,服務(wù)端渲染有著獨到的優(yōu)勢。它能提前再服務(wù)端中完成頁面模板的數(shù)據(jù)填充,從而一次性返回完整的首屏內(nèi)容,從而面對 SEO 的爬取時能獲取到更多有效的關(guān)鍵信息。
此外,由于其能快速直出首頁的真實數(shù)據(jù),體驗往往比 loading 態(tài)更佳,在 TTI 的表現(xiàn)上更為出色。
但是,服務(wù)端渲染也有其自身的局限性。因為從本質(zhì)上來說,SSR 服務(wù)無法完全與前端頁面解耦開來。因此市面上較完備的 SSR 解決方案都只解決首屏的服務(wù)端渲染,并采用同構(gòu)的方式,增加一層 node 中間層的方式來解決前端與 SSR 服務(wù)的更新同步問題,并與后端開發(fā)項目解耦。
但這無疑增加了項目的復(fù)雜度,并且隨著業(yè)務(wù)的復(fù)雜程度變高,服務(wù)端渲染往往需要調(diào)起多個接口去請求數(shù)據(jù)并填充頁面,這樣可能會導(dǎo)致在 TTFB 上有一定劣勢。
當(dāng)然,最重要的是,服務(wù)端渲染對于服務(wù)器的負(fù)載要求是很高的。

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

Native 渲染的本質(zhì)其實還是 SSR,只不過提供服務(wù)的 Server 轉(zhuǎn)變?yōu)榱丝蛻舳恕S捎谛枰玫娇蛻舳藱C(jī)能,因此此種實現(xiàn)通常應(yīng)用在移動端 APP,或者 PWA 下。
當(dāng)鏈接被點擊時,先借助瀏覽器啟用一個 JS 運(yùn)行時,并加載 APP 中存儲的 Html 模板,發(fā)送 xhr 請求預(yù)加載頁面數(shù)據(jù),從而在客戶端本地拼接并渲染生成一個有數(shù)據(jù)的 Html 首屏,形成首次 NSR。同時可以將該首屏 Html 緩存在客戶端,供下次頁面打開時,實現(xiàn) stale-while-revalidate 的緩存效果。
由于 NSR 將服務(wù)器的渲染工作放在了客戶端的一個個獨立設(shè)備中,既實現(xiàn)了頁面的預(yù)加載,同時又不會增加額外的服務(wù)器壓力。達(dá)到秒看的效果。
這種能力在擁有客戶端或者支持 PWA 的應(yīng)用中應(yīng)用廣泛,例如手 Q,騰訊文檔 APP 中都擁有通過 APP 中的離線包來實現(xiàn)首屏渲染加速的能力。
ESR(Edge Side Render)
那么,對于純 Web 應(yīng)用,而又由于兼容性等原因暫時無法支持 PWA 的頁面,有沒有一個合適的首屏渲染加速方案呢?
隨著云與邊緣計算的快速發(fā)展,前端頁面也需要考慮分布式的請求處理優(yōu)化。

我們知道,CDN 節(jié)點相比真實服務(wù)節(jié)點更貼近用戶,能更快將內(nèi)容返回。因此我們可以將靜態(tài)的 Html 內(nèi)容模板緩存在 CDN 上。當(dāng)接到請求時,先快速將靜態(tài)模板頁面返回給用戶,同時在 CDN 服務(wù)器上對頁面動態(tài)部分發(fā)起向后端發(fā)起請求,并將獲取到的動態(tài)內(nèi)容在以流式下發(fā)的方式繼續(xù)返回給用戶。
這里實際上利用到了 HTTP 的 SSE(Server Send Events)協(xié)議,通過服務(wù)器向客戶端發(fā)送單向事件流,實現(xiàn)同一個 Html 文件的分塊傳輸預(yù)渲染。