雙十一會場體驗 SSR 優(yōu)化 - 走向更復(fù)雜的渲染架構(gòu)

點(diǎn)擊上方藍(lán)色字體,關(guān)注我們

NO.1
前言
會場是每年雙十一的主角之一,會場的用戶體驗自然也是每年最關(guān)注的點(diǎn)。在日趨復(fù)雜的業(yè)務(wù)需求下,如何保障我們的用戶體驗不劣化甚至能更優(yōu)化是永恒的命題。
今年(2020)我們在不改變現(xiàn)有架構(gòu),不改變業(yè)務(wù)的前提下,在會場上使用了 SSR 技術(shù),將秒開率提高到了新的高度(82.6%);也觀察到在用戶體驗得到優(yōu)化的同時,業(yè)務(wù)指標(biāo)如 UV 點(diǎn)擊率等也有小幅的增長(視不同業(yè)務(wù)場景有不同的提升,最大可達(dá) 5%),帶來了不錯的業(yè)務(wù)價值。
本文將從服務(wù)端、前端兩個角度介紹我們在 SSR 上的方案與經(jīng)驗
前端在解決工程化、業(yè)務(wù)效果評估上的具體實踐與方法論
服務(wù)端在解決前端模塊代碼于服務(wù)端執(zhí)行、隔離和性能優(yōu)化上的具體實踐與方法論
NO.2
頁面體驗性能的核心指標(biāo)
在正文開始前我們先介紹一下衡量的相關(guān)指標(biāo),從多年前雅虎 yslow 定義出了相對完整的體驗性能評估指標(biāo),到后來的谷歌的 Lighthouse 等新工具的出現(xiàn),體驗性能的評估標(biāo)準(zhǔn)逐漸的統(tǒng)一且更加被大家認(rèn)同。
會場的評估體系
基于?Web.Dev(https://web.dev/)?以及其他的一些參考,我們定義了自己的簡化評估體系

TTFB(Time to First Byte): 第一個字節(jié)的時間 - 從點(diǎn)擊鏈接到收到第一個字節(jié)內(nèi)容的時間
FP(First Paint): 第一次繪制 - 用戶第一次看到任何像素內(nèi)容的時間
FCP(First Contentful Paint): 第一次內(nèi)容繪制 - 用戶看到第一次有效內(nèi)容的時間
FSP(First Screen Paint,首屏可視時間): 第一屏內(nèi)容繪制 - 用戶看到第一屏內(nèi)容的時間
LCP(Largest Contentful Paint): 第一次最大內(nèi)容繪制 - 用戶看到最大內(nèi)容的時間
TTI(Time To Interactive): 可交互時間 - 頁面變?yōu)榭山换サ臅r間(比如可響應(yīng)事件等)
大體上來說 FSP 約等于 FCP 或 LCP
NO.3
會場的現(xiàn)狀
我們的會場頁面是使用基于低代碼方案的頁面搭建平臺產(chǎn)出的,一個由搭建平臺產(chǎn)出的會場頁面簡單而言由兩部分組成:頁面框架(layout)和樓層模塊。

頁面框架有一份單獨(dú)的構(gòu)建產(chǎn)物(即頁面的 layout html 以及基礎(chǔ)公共的 js、css 等 assets 資源)。每個樓層模塊也有單獨(dú)的一份構(gòu)建產(chǎn)物(模塊的 js、css 等 assets 資源,基礎(chǔ)公共 js 的依賴版本信息等)。
頁面框架的任務(wù)比較繁雜,負(fù)責(zé)頁面的 layout、根據(jù)頁面的搭投數(shù)據(jù)加載具體哪些樓層模塊并組織分屏渲染模塊。
會場原有的 CSR 渲染架構(gòu)如下圖,可以分成三部分:
客戶端,包括手機(jī)淘寶等阿里系 App
文檔服務(wù),用于響應(yīng)頁面的主文檔 HTML 清求
數(shù)據(jù)服務(wù),用于響應(yīng)頁面的數(shù)據(jù)請求

原有的CSR渲染流程如下圖

針對會場的性能,除了基礎(chǔ)的大家都知道的前端優(yōu)化手段之外,還結(jié)合客戶端能力做過很多優(yōu)化方案,比較具有代表性的有兩個:
1. 客戶端主文檔/Assets 緩存
在客戶端內(nèi),我們利用了端側(cè)提供的靜態(tài)資源緩存能力,將 HTML 和基礎(chǔ)公共的 JS 等資源,推送下發(fā)至用戶側(cè)客戶端緩存。當(dāng)客戶端的 WebView 請求資源時,端側(cè)可根據(jù)規(guī)則來匹配已下發(fā)的緩存包,在匹配成功后直接從本地緩存中讀取對應(yīng)的 HTML 和 JS 資源,而無需每次都請求網(wǎng)絡(luò)、大大縮短了頁面的初始化時間
2. 數(shù)據(jù)預(yù)加載
從用戶點(diǎn)擊跳轉(zhuǎn)鏈接到頁面開始加載數(shù)據(jù),中間還要經(jīng)過客戶端動畫、WebView初始化、主文檔 HTML 請求以及基礎(chǔ)公共 js 的加載和執(zhí)行這些過渡階段,加起來有 幾百ms 的時間被浪費(fèi)掉。通過客戶端提供的數(shù)據(jù)預(yù)加載能力,在用戶點(diǎn)擊后就可以立即由 native 開始頁面的數(shù)據(jù)加載,等頁面的基礎(chǔ)公共 js 執(zhí)行完需要使用頁面數(shù)據(jù)時,直接調(diào)用 jsbridge 接口即可從 native 獲取已經(jīng)預(yù)先加載好的數(shù)據(jù)
在這些優(yōu)化工作的基礎(chǔ)上會場的體驗性能已經(jīng)可以達(dá)到不錯的水準(zhǔn)。
隨著時間的推移,基于我們 CSR 渲染體系下的優(yōu)化存在一些瓶頸:
在線上復(fù)雜網(wǎng)絡(luò)環(huán)境下(低網(wǎng)速、虛假的 WiFi)、Android 中低端機(jī)上的頁面體驗還是不盡人如意,特別是模塊的加載和執(zhí)行時間比較長,且這部分用戶的占比有增長趨勢
作為拉新的一個重要手段,外部喚起淘寶或者天貓客戶端因為需要時間來初始化一些功能組件,比如網(wǎng)絡(luò)庫等,頁面的體驗從體感上不能追平端內(nèi)的會場
會場是營銷活動性質(zhì)的業(yè)務(wù),頁面的復(fù)訪率相對較低,且頁面內(nèi)容全面?zhèn)€性化。離線的 HTML 快照等用戶側(cè)緩存手段會因為緩存的數(shù)據(jù)過期導(dǎo)致出現(xiàn)重復(fù)渲染(打開更慢)、頁面元素跳動(渲染閃爍、重排)等傷害體驗的問題
還有沒有優(yōu)化手段呢?以一個 2020 年雙十一會場頁面,使用 PC 上的 Chrome DevTools 的 performance 離線分析結(jié)果為例,我們看一下重點(diǎn)的問題

可以看到頁面從 FP 到 FCP 這段過渡的時間較長且只有背景色。FCP 到 LCP 這段時間處于等待圖片加載的時間,優(yōu)化空間較小,且難以衡量。
離線分析尚且如此,線上更有著復(fù)雜的網(wǎng)絡(luò)環(huán)境/差異化的手機(jī)機(jī)型等,這樣的“背景色”時間對用戶的體驗有很大的傷害,可能會讓用戶更加容易跳失。
我們的 CSR 渲染體系依賴前端+客戶端的能力,從工作機(jī)制上已經(jīng)很難再有比較大的提升。怎么才能讓會場頁面的體驗更上一層樓呢,我們想到了服務(wù)端渲染(SSR),?針對 FP 到 FCP 這段時間進(jìn)行攻堅優(yōu)化。

SSR 的線下測試結(jié)果,F(xiàn)P 到 FCP 從 825ms -> 408ms
NO.4
SSR 要怎么做?
大的方向
SSR 本身意為服務(wù)端渲染,這個服務(wù)端可以在?任何地方?,在 CDN 的邊緣節(jié)點(diǎn)、在云上的中心機(jī)房或者就在你家的路由上。
實現(xiàn)一個 SSR 的 demo,熟悉的人應(yīng)該都知道套路:
搞一個 Rax Server Renderer,傳入一個 Rax Component,renderToString,完事了
業(yè)界也已經(jīng)有很多實踐的案例,但就像“把大象裝進(jìn)冰箱里”一樣,看似簡單的事情在雙十一所要求的復(fù)雜場景穩(wěn)定性下,需要有穩(wěn)妥可實施的執(zhí)行方案。
如何在現(xiàn)有的這套模塊化、成熟的渲染架構(gòu)之上使用SSR呢,一開始我們往常規(guī)的思路去想,直接在文檔 HTML 響應(yīng)中返回服務(wù)端渲染完成的 HTML,看下來存在幾個問題:
改造成本高,對現(xiàn)有的服務(wù)端架構(gòu)改動比較大(CDN 緩存失效,文檔服務(wù)的要求更高)
無法復(fù)用現(xiàn)有的客戶端性能優(yōu)化能力,比如客戶端主文檔/Assets 緩存和數(shù)據(jù)預(yù)加載能力,會劣化完全可交互時間
CDN 緩存無法利用,TTFB 的時間增加,帶來了新的 “完全白屏階段”
SSR 服務(wù)不穩(wěn)定因素較多,自動降級為CSR的方案復(fù)雜,無法保證 100% 能夠降級
主文檔 HTML 的安全防護(hù)能力較弱,難以抵御黑產(chǎn)的惡意抓取
基于以上的問題,我們考慮是否還有其他的方案可以?低風(fēng)險?、?低成本?地實現(xiàn)SSR呢?經(jīng)過短暫且激烈的討論,我們設(shè)計了「數(shù)據(jù) SSR」架構(gòu)方案,分享給大家。
數(shù)據(jù) SSR 渲染架構(gòu)如下,文檔服務(wù)返回的內(nèi)容保持靜態(tài)化不變,數(shù)據(jù)服務(wù)新增調(diào)用一個獨(dú)立的 SSR FaaS 函數(shù),因為數(shù)據(jù)里有這張頁面包含的模塊列表和模塊需要的數(shù)據(jù),SSR FaaS 函數(shù)可以直接根據(jù)這些內(nèi)容動態(tài)加載模塊代碼并渲染出 HTML。

這套方案在客戶端內(nèi)的場景下可以很好的將 前端 + 客戶端 + 服務(wù)端三者的能力結(jié)合到一起。
有人可能會問,為什么這個方案會帶來性能提升呢?不就是把瀏覽器的工作移到了服務(wù)端嗎?我們舉個例子(數(shù)據(jù)僅為定性分析,不代表真實值)。在正常 CSR 渲染流程下,每段消耗的時間如下,首屏可視時間總共耗時1500ms。

在SSR渲染流程下,在「調(diào)用加載基礎(chǔ)js」之前的耗時都是一樣的,由于下面兩個原因,在服務(wù)端渲染的耗時會比客戶端低幾個數(shù)量級。
服務(wù)端加載模塊文件比在客戶端快很多,而且服務(wù)端模塊資源的緩存是公用的,只要有一次訪問,后續(xù)所有用戶的訪問都使用這份緩存。
服務(wù)端的機(jī)器性能比用戶手機(jī)的性能高出幾個數(shù)量級,所以在服務(wù)端渲染模塊的耗時很小。根據(jù)線上實際耗時統(tǒng)計,服務(wù)端單純渲染耗時平均 40ms 左右。
由于 HTML 被放到了數(shù)據(jù)響應(yīng)中,gzip 后典型值增加 10KB 左右,相應(yīng)的網(wǎng)絡(luò)耗時會增加 30~100ms不等。最終 SSR 的渲染流程及耗時如下,可以看到 SSR 首屏的可視時間耗時為660ms,比CSR提升了800ms。

總而言之,「數(shù)據(jù) SSR」的方案核心哲學(xué)是:將首屏內(nèi)容的計算轉(zhuǎn)移到算力更強(qiáng)的服務(wù)端
核心問題
大方向確定了,我們再來看看 SSR 應(yīng)用到生產(chǎn)中還存在哪些核心問題
如何做到 CSR/SSR 的平滑切換
開發(fā)者如何開發(fā)出“能 SSR”的代碼
開發(fā)者面向前端編寫的代碼在服務(wù)端運(yùn)行的不可控風(fēng)險
低代碼搭建場景下,在服務(wù)端解決樓層模塊代碼加載的問題
服務(wù)端性能
怎么衡量優(yōu)化的價值
別急,我們一個一個的來看解法
如何做到 CSR/SSR 的平滑切換?
在我們的頁面渲染方案中,有兩個分支:
頁面未開啟數(shù)據(jù)SSR,則與原有的 CSR 渲染流程一樣,根據(jù)數(shù)據(jù)中的模塊列表加載模塊并渲染
頁面開啟了數(shù)據(jù)SSR并且返回的數(shù)據(jù)中有 SSR HTML,則使用 SSR 的 HTML 塞入到 root container 中,然后根據(jù)數(shù)據(jù)中的模塊列表加載模塊最終 hyrdate。

優(yōu)點(diǎn)很明顯
風(fēng)險低,能夠無縫降級到CSR,只需要判斷數(shù)據(jù)接口的響應(yīng)中是否成功返回 HTML 即可。如果 SSR 失敗或者超時(未返回 HTML),通過設(shè)置合理的服務(wù)端超時時間(例如 80ms),不會影響到用戶的最終體驗
能夠利用端上成熟的性能優(yōu)化能力,比如客戶端緩存能力,數(shù)據(jù)預(yù)加載能力。有客戶端緩存能力,頁面的白屏?xí)r間與原CSR一致;有了數(shù)據(jù)預(yù)加載能力,能夠在頁面加載之前就開始請求數(shù)據(jù)服務(wù)
在線上服務(wù)時,我們可以通過 HASH 分桶的方式對流量進(jìn)行劃分,將線上的流量緩慢的切換到 SSR 技術(shù)方案,既能保證穩(wěn)定性,同時還可以方便的進(jìn)行業(yè)務(wù)效果的進(jìn)一步評估。
比較好的字符串轉(zhuǎn)換為數(shù)字的?HASH 方法(http://www.cse.yorku.ca/~oz/hash.html)有 DJBHash,驗證下來分桶效果較為穩(wěn)定
開發(fā)者如何開發(fā)出“能 SSR”的代碼?
很多做 SSR “demo”分享的往往會忽略一個重要點(diǎn):開發(fā)者
在雙十一的場景下,我們有百+的開發(fā)者,三百+的樓層模塊,如何能推動這些存量代碼升級,降低開發(fā)者的改造適配成本是我們的一個核心方向。
我們原有的樓層模塊構(gòu)建產(chǎn)物分為 PC/H5/Weex 三個,業(yè)界通用的是針對 SSR,單獨(dú)構(gòu)建一個 target 為 node 的構(gòu)建產(chǎn)物。在實際 POC 驗證過程中,我們發(fā)現(xiàn)其實絕大部分的模塊并不需要改造就可以直接適配 SSR,而新增構(gòu)建產(chǎn)物會牽扯到更多的開發(fā)者,于是想找尋別的解決方案。

復(fù)用現(xiàn)有 Web 構(gòu)建產(chǎn)物的一個問題是,Webpack 4 默認(rèn)會注入一些 Node 環(huán)境相關(guān)變量(https://v4.webpack.js.org/configuration/node/#nodeprocess),會導(dǎo)致常用的組件庫中的類似const isNode = typeof process !== 'undefined' && process && process.env?的判斷異常。不過還好這個是可以關(guān)閉的,開發(fā)環(huán)境下其他的類似devServer?等的注入也是可以關(guān)閉的,這給了我們一點(diǎn)慰藉,最終復(fù)用了 Web 的構(gòu)建產(chǎn)物。像更新的 Webpack 5 中把 target 的差異給弱化了,也可以更好的定制,讓我們未來有了更好的社區(qū)化方向可以繼續(xù)靠攏。
解決完構(gòu)建產(chǎn)物的問題,在本地開發(fā)階段,Rax 團(tuán)隊提供了 VSCode SSR 開發(fā)插件,集成了一些 best practice 以及 lint 規(guī)則,寫代碼的時候就可以發(fā)現(xiàn) SSR 的相關(guān)問題,及時規(guī)避和修復(fù)。

同時我們模擬真實線上的環(huán)境,在本地提供了 Webpack 的 SSR 預(yù)覽調(diào)試插件,直接 dev 就可以看到 SSR 的渲染結(jié)果。
針對開發(fā)者會在代碼中直接訪問window?、location?等變量的場景,我們一方面開發(fā)了統(tǒng)一的類庫封裝調(diào)用抹平差異,另一方面在服務(wù)端我們也模擬了部分常用的瀏覽器宿主變量,比如window?、location?、navigator?、document??等等,再加上與 Web 共用構(gòu)建產(chǎn)物,所以大部分模塊無需改造即可在服務(wù)端執(zhí)行。
接下來的模塊發(fā)布階段,我們在工程平臺上增加了發(fā)布卡口,若在代碼靜態(tài)檢查時發(fā)現(xiàn)了影響 SSR 的代碼問題就阻止發(fā)布并提示修復(fù)。

由于實際的業(yè)務(wù)模塊量較大,為了進(jìn)一步縮小改造的范圍,測試團(tuán)隊聯(lián)合提供了模塊的批量測試解決方案。具體的原理是構(gòu)造一個待改造模塊的 mock 頁面,通過比較頁面 SSR 渲染后的截圖與 CSR 渲染后的截圖是否一致,來檢測SSR 的渲染結(jié)果是否符合預(yù)期

開發(fā)者面向前端編寫的代碼在服務(wù)端運(yùn)行的不可控風(fēng)險
盡管我們在開發(fā)階段通過靜態(tài)代碼檢查等方法極力規(guī)避問題,實際上仍然存在一些針刺痛著我們的心
開發(fā)者把全局變量當(dāng)緩存用造成內(nèi)存泄露
錯誤的條件結(jié)束語句導(dǎo)致死循環(huán)
未知情況頁面上存在不支持 SSR 的模塊
這些疑難點(diǎn)從 SSR 的機(jī)制上其實很難解決,需要有完善的自動降級方案避免對用戶的體驗造成影響。
在說更詳細(xì)的方案前要先感謝我們自己,前端已經(jīng)提前做到了 CSR/SSR 的平滑切換,讓服務(wù)端能每天不活在恐懼里 = =
對于機(jī)制上的問題,可以引申閱讀到之前分享過的 《在 Node.js 中 ”相對可靠” 的高效執(zhí)行可信三方的代碼》。我們這里主要聚焦在如何快速止血與恢復(fù)。

FaaS 給服務(wù)端降低了非常大的運(yùn)維成本,“一個函數(shù)做一件事”的設(shè)計哲學(xué)也讓 SSR 的不穩(wěn)定性局限在了一塊很小的部分,不給我們帶來額外的運(yùn)維負(fù)擔(dān)。
低代碼搭建場景下,在服務(wù)端解決樓層模塊代碼加載的問題
業(yè)界分享的一些 SSR 場景基本都是整頁或者 SPA 類型的,即 SSR 所使用的 bundle 是將整頁完整的代碼構(gòu)建后暴露出一個 Root Component,交由 Renderer 渲染的。而我們的低代碼搭建場景,由于整個可選的模塊池規(guī)模較大,頁面的樓層模塊是動態(tài)選擇、排序和加載的。這在前端 CSR 情況下很方便,只要有個模塊加載器就可以了,但是在服務(wù)端問題就比較復(fù)雜。

還好我們的模塊規(guī)范遵守的是特殊的 CMD 規(guī)范,有顯式的依賴關(guān)系聲明,可以讓我們在獲取到頁面的樓層組織信息之后一次性的把頁面首屏的全部 Assets 依賴關(guān)系計算出來。
/**示例的 CMD 規(guī)范顯式依賴關(guān)系(seed)**/{"packages": {"@ali/pcom-alienv": {"path": "//g.alicdn.com/code/npm/@ali/pcom-alienv/1.0.2/","version": "1.0.2"},"modules": {"./index": ["@ali/pcom-alienv/index"]}}
在服務(wù)端加載到代碼后,我們就可以拼裝出一個 Root Component 交給 Renderer 渲染了。
服務(wù)端性能
性能上主要是有幾個方面的問題
機(jī)制問題
代碼問題
機(jī)制問題
由于樓層模塊很多,在實際執(zhí)行的過程中發(fā)現(xiàn)存在一些機(jī)制上的性能問題
代碼的 parse 時間較長且不穩(wěn)定
流量較低情況下難以觸發(fā) JIT
優(yōu)化方案的話比較 tricky
緩存?
vm.Script?實例,避免重復(fù) parse期望一致性 HASH 或自動擴(kuò)縮容(本次未實現(xiàn))
巡檢的時候還觀測到存在小范圍的 RT 抖動問題,分析后定位是同步的 renderToString 調(diào)用在微觀上存在排隊執(zhí)行的問題

在這種情況下會造成部分渲染任務(wù)的 RT 為多個排隊任務(wù)的渲染 RT 疊加,影響單個請求的 RT(但不影響吞吐量)。這種問題要求我們需要更精確的評估備容的資源。機(jī)制上有效的解法推測可以讓?renderToString?以 fiber 的方式執(zhí)行,緩解微觀排隊造成的不公平的問題。
代碼問題
性能問題的分析當(dāng)然免不了 CPU Profile,拿出最愛的 alinode 進(jìn)行分析,很快的可以找到熱點(diǎn)進(jìn)行針對性優(yōu)化。

上圖中標(biāo)藍(lán)的方法為 CMD 加載器計算依賴的熱點(diǎn)方法,對計算結(jié)果進(jìn)行緩存后熱點(diǎn)消除,整體性能提升了 80%?
怎么衡量優(yōu)化的價值
這么多的投入當(dāng)然需要完善的評價體系來進(jìn)行評價,我們從體驗性能和業(yè)務(wù)收益兩個分別評估。
體驗性能
基于兼容性較好的?PerformanceTiming?(將被 PerformanceNavigationTiming 替代),我們可以獲取到前端范疇下的一些關(guān)鍵的時間
navigationStart
firstPaint
其中?navigationStart?將會作為我們的前端起點(diǎn)時間所使用。在前端之外,對用戶的交互路徑而言真正的起點(diǎn)是在客戶端的點(diǎn)擊跳轉(zhuǎn)時間?jumpTime?,我們也聯(lián)合客戶端進(jìn)行了全鏈路埋點(diǎn),將客戶端 native 的時間與前端的時間串聯(lián)了起來,納入到我們的評價體系中。
在最開始的核心指標(biāo)中,我們看到有 FCP、TTI 這幾個指標(biāo)。目前的 Web 實現(xiàn)中,還未有兼容性較好的可以線上衡量的方案(線下可以使用 DevTools 或者 Lighthouse 等工具),因此我們通過其他的方式來做近似代替
| CSR | SSR | |
| FCP | componentDidMount | innerHTML to Body |
| TTI | componentDidMount | componentDidMount |
線上取到的數(shù)據(jù)通過 tracker 的方式進(jìn)行無采樣上報,最終我們可以通過多個維度進(jìn)行分析
機(jī)型
網(wǎng)絡(luò)條件
是否命中 SSR
是否命中其他前端優(yōu)化
主要的衡量指標(biāo)有
從用戶點(diǎn)擊到 FCP 的時間(FCP - jumpTime)
從 NavigationStart 到 FCP 的時間(FCP - NavigationStart)
業(yè)務(wù)收益
這部分很忐忑,體驗的優(yōu)化是否會帶來真金白銀的收益呢?我們直接通過 AA 和 AB 實驗進(jìn)行業(yè)務(wù)數(shù)據(jù)的分析。
基于之前的切流分桶,我們可以通過類似?hash 值 % 10?的方式將流量分為 0~9 號十個桶,首先通過 AA 實驗驗證分桶是否均勻
桶號 | 0 | 1 | 2 | 3 | ... |
PV | 100 | 101 | 99 | 98 | |
UV | 20 | 21 | 22 | 20 |
統(tǒng)計指標(biāo)舉例
這一步是保證分桶的邏輯本身不會有數(shù)據(jù)的傾斜影響置信度。接下來我們再進(jìn)行 AB 實驗,逐步增加實驗桶驗證業(yè)務(wù)數(shù)據(jù)的變化。
最終的效果
搞了這么多,得看看產(chǎn)出了。在這次雙十一會場中,我們切流了多個核心的頁面,拿到的第一手?jǐn)?shù)據(jù)分享給大家。
潮流女裝會場 | CSR | SSR |
| 從用戶點(diǎn)擊到 FSP 的時間小于 1s 的比例 | iOS 66% Android 28% | iOS 86% +30% Android 60% +114% |
UV 點(diǎn)擊率提升 | +5% |

小米5 驍龍 820 處理器
可以看到,在 Android 碎片化的生態(tài)的下,帶來的提升甚至超出了預(yù)期,這也給了我們未來更大的動力,將前端 + 客戶端 + 服務(wù)端的能力更有效的結(jié)合到一起,帶給用戶更好的體驗,給業(yè)務(wù)創(chuàng)造更大的價值。
NO.5
未來的渲染架構(gòu)還會更復(fù)雜嗎?
為了更好的用戶體驗,當(dāng)然會了!我們可以簡單的看看短期和長期的一些事情
電商體驗指標(biāo)的統(tǒng)一定義
長期以來,業(yè)務(wù)在用戶側(cè)的實現(xiàn)有 Web、Native、Hybrid 混合開發(fā)等多種選擇,每個體系都有著自己的封閉體驗衡量標(biāo)準(zhǔn),這就造成了一些“雞同鴨講”的問題。而 Web.dev 中所定義的 FCP、LCP 通用評價體系也并不適合電商場景,能展示出核心的商品/店鋪其實對一張頁面來說就完成了它的使命。
后續(xù)我們可以將體驗指標(biāo)評估標(biāo)準(zhǔn)對齊,將起點(diǎn)時間、繪制完成時間等在多個體系對齊概念與實現(xiàn),達(dá)到互相之間可以橫向比較良性競爭的狀態(tài)。
工程上還有更多的事情要做...
在 Webpack 5 的 Release Note 中,我們可以看到 Webpack 正在弱化 target 的一些特殊處理,將 Web 描述為了?browserlike?的環(huán)境。同時還提供了自定義 browserlist 的能力,可以給予開發(fā)者更方便處理跨端的兼容性問題的能力。這一變化將推動我們更快的擁抱社區(qū),獲得更好的開發(fā)體驗。
現(xiàn)有的 SSR 靜態(tài)代碼檢查方案會有一些漏網(wǎng)之魚,還有沒有更完善的方案能從工程上前置解決代碼風(fēng)險(性能、安全)問題也是未來的一個方向。
ServiceWorker Cache 離線緩存快照
復(fù)訪率高,變化不太大的頁面可以利用 ServiceWorker Cache 等方案,將之前的渲染結(jié)果緩存下來,命中緩存直接用,未命中緩存 SSR。降低服務(wù)端壓力的同時可以讓體驗更好。
SSR 的性能優(yōu)化與安全
現(xiàn)階段的 Node.js 或者說 V8,對于動態(tài)加載代碼的情況支持并沒有特別的完善,缺失了安全相關(guān)的保護(hù)邏輯。并且從性能上來說,SSR 屬于 CPU 密集型的 workload,純異步的優(yōu)勢并不明顯,也可能需要一些特殊的解決方案來配合。
外部投放場景的覆蓋
「數(shù)據(jù) SSR」的方案是端內(nèi)的最佳方案,卻是外投場景的最劣方案。外投場景下由于用戶是在第三方 App 中打開頁面,相應(yīng)的缺失了客戶端的定制化優(yōu)化能力,SSR 調(diào)用會造成數(shù)據(jù)服務(wù)的 RT 增加,反而推后了 FCP。
這時候古老的 HTML 直出方案又可以再撈回來了。

核心在于
利用 CDN 的邊緣計算能力,可以較好的做到“動靜分離”以及容災(zāi)
使用中心化的 SSR 函數(shù),可以將 SSR 的不穩(wěn)定性與 CDN 的可靠性分離,保證近端鏈路的可靠,避免出現(xiàn)近端直接不可用導(dǎo)致的無法恢復(fù)
近端的流式方案經(jīng)常被提及,但是在實際的使用中會遇到當(dāng)流式輸出遇到錯誤時,用戶側(cè)無法有效容災(zāi)的問題(HTML 損毀,無法補(bǔ)救)。通過“動靜分離”可以將頁面分為

僅將 Root Container 進(jìn)行動態(tài)化,進(jìn)而在享用流式輸出帶來的 TTFB 提前的好處的同時又能兼顧容災(zāi) SSR 的不穩(wěn)定。和業(yè)務(wù)團(tuán)隊更可以一起探討下如何將頁面更好的從業(yè)務(wù)上做到“動靜分離”,而不是僅從技術(shù)的角度出發(fā)。
NO.6
總結(jié)
渲染架構(gòu)的不斷改進(jìn)實質(zhì)上是我們在有限且變化的環(huán)境下(終端性能、復(fù)雜網(wǎng)絡(luò)和多變業(yè)務(wù))自發(fā)做的適應(yīng),也許有那么一天,環(huán)境不再是問題,性能優(yōu)化的課題將會消失。我們項目組有時候還開玩笑,等明年手機(jī)叒換代了,5G 100% 普及了,是不是這些優(yōu)化都可以下線了?
但是!現(xiàn)在看理想還有點(diǎn)遠(yuǎn),在 2020 的雙十一會場我們走進(jìn)了一個新的深水區(qū),期待未來技術(shù)與業(yè)務(wù)結(jié)合能帶給廣大用戶更棒的體驗!
喜歡就點(diǎn)這里

