從 “卡頓” 到 “秒開”:外投首屏性能優(yōu)化的六個(gè)實(shí)戰(zhàn)錦囊

一、背景
在互聯(lián)網(wǎng)時(shí)代,網(wǎng)站性能的好壞直接影響用戶體驗(yàn)和轉(zhuǎn)化率。對(duì)投放的廣告頁面而言,如何在保證視覺效果和功能的同時(shí)提升加載速度,成為了開發(fā)者必須面對(duì)的挑戰(zhàn)。
本文將探討幾種有效的外投頁面性能優(yōu)化策略,包括構(gòu)建方式的優(yōu)化、非首屏組件的處理、關(guān)鍵大圖的預(yù)載、動(dòng)效方面的升級(jí),以及針對(duì)弱網(wǎng)環(huán)境下的降級(jí)策略、外投流渲染的技術(shù)升級(jí)等相關(guān)內(nèi)容。
二、難點(diǎn) & 收益
首屏秒開率口徑嚴(yán)格
首屏秒開率通常指用戶從觸發(fā)頁面加載(如點(diǎn)擊廣告鏈接)開始,到首屏內(nèi)容完全渲染完成,并可進(jìn)行交互所花費(fèi)的時(shí)間在 1 秒以內(nèi)的比例。其中,“首屏內(nèi)容” 指用戶設(shè)備屏幕可見區(qū)域內(nèi)的全部內(nèi)容,包括文字、圖片、按鈕等關(guān)鍵信息元素。
“完全渲染完成” 不僅要求視覺上顯示完整,還需保證頁面元素的布局穩(wěn)定,不存在閃爍、錯(cuò)位等情況;“可交互” 則意味著用戶能夠?qū)κ灼羶?nèi)的交互元素(如按鈕、輸入框)進(jìn)行有效操作,不會(huì)出現(xiàn)點(diǎn)擊無響應(yīng)的情況。
投放環(huán)境復(fù)雜
外投頁面的投放環(huán)境極為復(fù)雜。用戶可能分布在不同網(wǎng)絡(luò)環(huán)境中,包括 4G、5G、Wi-Fi 甚至弱網(wǎng)或不穩(wěn)定網(wǎng)絡(luò)環(huán)境,在 2G、3G 等低速網(wǎng)絡(luò)或信號(hào)波動(dòng)較大的區(qū)域,數(shù)據(jù)傳輸速率受限,資源加載容易出現(xiàn)延遲。而且,用戶使用的設(shè)備性能差異懸殊,從高端旗艦機(jī)到中低端老舊設(shè)備,硬件配置的不同會(huì)導(dǎo)致頁面解析、渲染能力參差不齊,部分低端設(shè)備難以快速處理復(fù)雜的頁面代碼和資源。
頁面收益
經(jīng)過長達(dá)兩個(gè)季度的性能優(yōu)化專項(xiàng)工作,外投頁面取得了顯著的收益:
- 外投頁面曝光率提高了10%左右
 - 首屏秒開率從15%提高到65%左右
 
三、外投頁面的渲染策略
在構(gòu)建現(xiàn)代 web 應(yīng)用時(shí),SSR(Server-Side Rendering)是常用的渲染方式,但我們外投頁面大部分頁面采用的是ISR,字面上理解,可以理解為SSR+SSG??梢詤⒖枷旅孢@張圖。

在初次構(gòu)建時(shí),ISR 會(huì)像 SSG 一樣預(yù)生成靜態(tài)頁面,并將其部署到服務(wù)器或 CDN。
當(dāng)用戶訪問頁面時(shí),若頁面已經(jīng)過期,ISR 會(huì)觸發(fā)一個(gè)后臺(tái)再生成過程。這個(gè)過程在服務(wù)器端完成,類似于 SSR,但與 SSR 不同的是,再生成的頁面會(huì)被存儲(chǔ)為靜態(tài)文件,而非每次請(qǐng)求都進(jìn)行實(shí)時(shí)渲染。
具體再生流程
- 用戶請(qǐng)求過期的頁面時(shí),ISR 會(huì)啟動(dòng)一個(gè)后臺(tái)再生成過程。
 - 服務(wù)器重新生成頁面,并將新的 HTML 文件更新到緩存中。
 - 在生成過程完成后,下一個(gè)用戶請(qǐng)求將會(huì)獲得更新后的頁面。
 
舉個(gè)例子,假設(shè)一個(gè) Next.js 頁面設(shè)置了 revalidate 選項(xiàng)為 10 秒,這意味著頁面在構(gòu)建時(shí)將會(huì)生成靜態(tài) HTML 文件,并在 10 秒內(nèi)保持不變。
具體流程
- 0-10 秒:在初始構(gòu)建完成后的前 10 秒內(nèi),用戶請(qǐng)求的 HTML 文件都是之前生成的靜態(tài)頁面。頁面不會(huì)重新生成,所有請(qǐng)求都直接返回緩存的靜態(tài)頁面。
 - 10 秒后:當(dāng)?shù)谝粋€(gè)請(qǐng)求到達(dá)并發(fā)現(xiàn)頁面已經(jīng)過期時(shí)(超過了 10 秒),ISR 會(huì)啟動(dòng)一個(gè)后臺(tái)再生成過程。此時(shí),服務(wù)器仍然會(huì)返回舊的緩存頁面給用戶,同時(shí)在后臺(tái)生成新的頁面。
 - 生成完成后:當(dāng)后臺(tái)生成的頁面完成后,下一個(gè)用戶請(qǐng)求將會(huì)得到新的頁面。新生成的頁面會(huì)被存儲(chǔ)為緩存靜態(tài)文件,并在后續(xù)的 10 秒內(nèi)繼續(xù)使用,直到再次觸發(fā)再生成過程。
 
這種機(jī)制保證了頁面在大部分時(shí)間內(nèi)快速響應(yīng),同時(shí)能夠在后臺(tái)靜默地更新內(nèi)容,確保用戶能盡快看到最新的數(shù)據(jù)。
外投主要是幾個(gè)固定頁面,此處作如下分類。
分類
- 交互性交強(qiáng)的頁面, 如盲盒這類頁面的特點(diǎn),放量占比流量大,首屏秒開受動(dòng)效影響較大,一般配置完運(yùn)營就短期內(nèi)不會(huì)進(jìn)行更新,適合ISR。頁面靜態(tài)內(nèi)容為主。
 - 容器頁面用于進(jìn)行效果AB測(cè)試的頁面,不太適合用ISR,在構(gòu)建時(shí)獲取AB的結(jié)果, 實(shí)時(shí)性要求較高,AB的結(jié)果因人而異,采用SSR策略。
 - 變更比較頻繁的頁面,不接受短時(shí)間的差異的,這種一般采取SSR策略。
 
不足:使用ISG構(gòu)建的頁面, 在于客戶端和客戶端建聯(lián)的時(shí)候,需要等待HTML文檔全部下載完成,瀏覽器才開始渲染,所以ISG構(gòu)建的頁面 TTFB 都會(huì)比較大。若一個(gè)網(wǎng)頁的TTFB 較慢,后續(xù)的FMP、LCP、FCP 等所有指標(biāo)都會(huì)很難提高, 所以在此基礎(chǔ)上,我們?cè)赒1啟動(dòng)了外投落地頁的流渲染的技術(shù)架構(gòu)升級(jí),具體會(huì)在本篇文章的第四段詳細(xì)介紹。
四、組件懶加載
在優(yōu)化頁面加載時(shí),非首屏組件的渲染方式至關(guān)重要。比如頁面的挽留彈窗,頁面的二級(jí)彈窗,這些都屬于非首屏的內(nèi)容。 可通過組件的封裝和抽取,區(qū)分首屏組件和首屏組件,哪些需要直出dom,哪些無需直出dom,可以在客戶端在進(jìn)行渲染,這里 通過使用 Next.js的 next/dynamic 實(shí)現(xiàn)組件的動(dòng)態(tài)加載,可以將這些非首屏組件的 SSR 設(shè)置為 false ,在用戶點(diǎn)擊到了到相應(yīng)位置時(shí)再進(jìn)行加載。這種懶加載策略最直接影響的首屏的bundle(js、css),追求極致的首屏體積。
const DyamicMarqueeTop = dynamic(() => import('./marqueTop'), {
  ssr: false,
  loading: () => <div></div>,
})
const DyamicDialog = dynamic(() => import('./dialog'), {
  ssr: false,
  loading: () => <div></div>,
})下面是優(yōu)化前后的外投H5頁面對(duì)比, 大圖模板 預(yù)計(jì)減少5.3kB。

商品流模板

五、圖片preload策略
對(duì)于外投頁面而言,影響首屏秒開的有的是一些關(guān)鍵性大圖。為了提升大圖的加載效率,可以在 HTML 的 <head> 中使用 <link rel="preload"> 標(biāo)簽提前加載關(guān)鍵大圖。這種做法能夠在用戶訪問頁面時(shí),優(yōu)先加載重要的視覺元素,從而減少用戶等待時(shí)間。
import Head from 'next/head'
/** 單品圖模板自定義的頭的一些 業(yè)務(wù)邏輯 */
export const ScratchHead = () => {
  const defaultUrl = 'xx'
  
  const scratchInfo = global?.componentList?.find((item: { name: string }) => item.name === 'scratchCard')
  
  const bg = scratchInfo?.props?.bgImg || defaultUrl
  
  return (
    <>
      <Head>
        <link rel="preload" href={`${bg}?x-oss-process=image/format,webp/resize,w_750`} as="image" />
      </Head>
    </>
  )
}六、外投動(dòng)畫升級(jí)
現(xiàn)狀
由于盲盒玩法,流量波動(dòng)比較大,優(yōu)化盲盒玩法的首屏秒開優(yōu)先級(jí)較高。
結(jié)合apm上報(bào)的路徑,這是一個(gè)canvas容器。
html.support-webp > body > div#__next > div > div > div > canvas初步定位為,需要頁面的動(dòng)畫渲染影響了整體秒開,于是我們推動(dòng)產(chǎn)品和設(shè)計(jì)同學(xué) 進(jìn)行動(dòng)畫升級(jí)從現(xiàn)有的apng升級(jí)到lottie。
75分位的首屏秒開 從 4.8s 多下降到 1.8s 左右, 首屏秒開提升16pp左右。

為什么升級(jí)一個(gè)動(dòng)效,就對(duì)頁面的秒開影響之大?
apng
在沒全量應(yīng)用lottie之前,外投針對(duì)復(fù)雜動(dòng)畫的處理一直都是apng,可以說是苦apng久已。
- apng的缺點(diǎn)在于資源體積非常大,一般的動(dòng)畫都得達(dá)到2-4M, 光資源加載就要好幾秒了,何談首屏秒開。
 - 由于apng有瀏覽器兼容性問題,對(duì)于apng資源的播放我們都是將apng解碼,然后每一幀的圖片用canvas 畫布進(jìn)行渲染。
 - 由于動(dòng)畫的容器是canvas,無法首屏直出dom,只能等到客戶端場(chǎng)景下載JS,加載資源后再進(jìn)行渲染, 這就是含有動(dòng)畫模板秒開比較低的本質(zhì)原因。
 
(下面的流程圖均是cursor結(jié)合excalidraw自動(dòng)生成出的)
染apng具體流程

lottie
為了解決上訴問題, 我們第一時(shí)間想到了lottie 動(dòng)畫, 對(duì)于首屏關(guān)鍵的動(dòng)畫從apng 直接轉(zhuǎn)到lottie。
lottie的文件體積通常較小,因?yàn)樗且?JSON 數(shù)據(jù)的形式存儲(chǔ)動(dòng)畫信息,而非實(shí)際的圖像幀。對(duì)于復(fù)雜的動(dòng)畫,尤其是包含大量圖形元素和動(dòng)畫效果的情況,Lottie 的文件大小優(yōu)勢(shì)更為明顯??梢钥聪旅鎸?duì)比圖:

同樣一個(gè)動(dòng)畫播放, apng 需要將近2M多,但是lottie需要的資源僅僅需要幾百k,資源體積下降十分明顯。
設(shè)計(jì)師通常給到的lottie資源是這樣的:

開發(fā)往往需要對(duì)設(shè)計(jì)師給到的lottie文件進(jìn)行cdn 化處理:
第一步: 需要壓縮圖片資源,然后上傳到OSS。
第二步: 然后替換json 中的 assests 路徑。
第三步: 上傳lottie.json,生成一個(gè)url,供我們前端進(jìn)行渲染。
對(duì)于這些復(fù)雜的操作,我們已經(jīng)內(nèi)置為一個(gè)npm 包@dw/lottie-cli,專門用于處理設(shè)計(jì)師給的lottie資源,同時(shí)封裝了基于react的lottie組件。
- lottie-cli支持 tinify圖片壓縮
 - 支持webp生成
 - lottie-player 支持 webp 渲染
 

lottie的缺點(diǎn),在于依賴一個(gè)lottie-web的運(yùn)行時(shí),以及l(fā)ottie.json 資源的大小,至于方案如何選擇,還是要具體業(yè)務(wù)具體分析。沒有完美的方案,找到適合當(dāng)前頁面的動(dòng)效才是最好的。
減少runtime體積
lottie動(dòng)畫依賴的lottie-web沒法做到tree-shaking,因此修改外投引入lottie的方式。將lottie js 體積包拆分成 svg、html、canvas. 三種渲染依賴JS ,將運(yùn)行時(shí)體積從80kb降低到40kb,首屏秒開預(yù)計(jì)提升100ms。
優(yōu)化前

優(yōu)化后

針對(duì)lottie動(dòng)畫SSR場(chǎng)景下沒法直出dom的情況,新增lottie動(dòng)畫預(yù)渲染骨架。在SSR場(chǎng)景,用動(dòng)畫的第一幀dom,作為lottie動(dòng)畫的骨架(只適用于lottie渲染模式 是用svg 或者是html,canvas模式不支持 ),首屏秒開提升100ms。
優(yōu)化前

優(yōu)化后

七、低端機(jī)和弱網(wǎng)優(yōu)化
為保障所有用戶都能收獲良好使用體驗(yàn),在這個(gè)過程中,尤其需要關(guān)注那些使用低端機(jī)器的用戶群體。針對(duì)這部分用戶,我們可制定相應(yīng)的降級(jí)策略,比如跳過動(dòng)畫展示環(huán)節(jié)。具體實(shí)施時(shí),通過對(duì)用戶設(shè)備性能進(jìn)行檢測(cè),以此來決定是否加載動(dòng)畫元素,進(jìn)而確保頁面在性能相對(duì)較低的設(shè)備上也能夠保持流暢運(yùn)行。
弱網(wǎng)指標(biāo)判斷
弱網(wǎng)的初步定義
當(dāng)網(wǎng)絡(luò)的往返時(shí)間(RT)大于 150ms 時(shí),便認(rèn)定其處于弱網(wǎng)狀態(tài)。
網(wǎng)絡(luò)性能檢測(cè)方法
針對(duì)同一張小體積圖片,在每次訪問時(shí)都對(duì)其進(jìn)行訪問操作,并計(jì)算相應(yīng)的往返時(shí)間(RT)。我們將該 RT 值作為此次訪問網(wǎng)絡(luò)性能的代表指標(biāo),通常情況下,RT 值越短,則意味著網(wǎng)絡(luò)性能越佳。
低端機(jī)指標(biāo)判斷
核心判定邏輯
綜合考量去navigator上的 deviceMemory、hardwareConcurrency、saveData 以及顯示屏幕、觸摸屏幕等方面的信息,以此構(gòu)成判斷低端機(jī)的初步標(biāo)準(zhǔn)。
具體判定細(xì)則
- 內(nèi)存方面:若 deviceMemory 的值小于等于 2GB,那么可直接判定該設(shè)備為低端設(shè)備。
 - CPU 方面:當(dāng) navigator.hardwareConcurrency 的數(shù)值小于 4 時(shí),同樣能夠直接判定此設(shè)備屬于低端設(shè)備范疇。
 - 設(shè)備像素方面:倘若設(shè)備像素低于 600,那么該設(shè)備可被判定為極端設(shè)備。
 
卡頓指標(biāo)判斷
卡頓指標(biāo)的檢測(cè)邏輯
針對(duì)卡頓指標(biāo)的檢測(cè),我們采取如下方式:通過創(chuàng)建一批div元素,并為其施加動(dòng)畫效果,以此來測(cè)試設(shè)備的性能表現(xiàn),隨后給當(dāng)前設(shè)備進(jìn)行打分,最終依據(jù)分?jǐn)?shù)的高低來區(qū)分不同性能的機(jī)器。具體的卡頓判定標(biāo)準(zhǔn)如下:
- 若渲染時(shí)間大于 60ms,這種情況可被視作存在發(fā)生卡頓的可能性。
 - 而一旦渲染時(shí)間超過 200ms,那么就認(rèn)定該設(shè)備出現(xiàn)了嚴(yán)重卡頓的情況。
 
收集到上述指標(biāo)后,最終落地到頁面就是動(dòng)畫跳過,或者是動(dòng)畫降級(jí),從動(dòng)畫變成一張靜態(tài)圖,或者是在不阻塞主流程的情況下, 走下一步跳過動(dòng)畫。
偽代碼如下:
// 是低端機(jī)或者是弱網(wǎng)設(shè)備
if (isLowEndDevice || isLowNetWork) {
  // 跳過動(dòng)畫
} else {
  // 加載動(dòng)畫
}降級(jí)策略
移動(dòng)端設(shè)備,針對(duì)我們外投頁面而言,影響比較大的兩個(gè)因素:
- 弱網(wǎng)
 - 設(shè)備性能
 
安卓設(shè)備性能小于IOS 設(shè)備,安卓設(shè)備解析JS的時(shí)間長,在弱網(wǎng)的情況下,用戶加載JS的時(shí)間比較長。
Lotttie動(dòng)畫降級(jí)
a. 主要是針對(duì)lottie 文件的assets 圖資源進(jìn)行降級(jí)。

b. 針對(duì)低端機(jī)型直接跳過動(dòng)畫,直接使用lottie預(yù)構(gòu)建的骨架, 保證SSR的dom直出。
動(dòng)畫降級(jí)方案
目前外投播放apng 動(dòng)畫的流程涉及到如:

一個(gè)apng的動(dòng)畫的播放生命周期,涉及到資源拉取時(shí)間 + 解析apng 的時(shí)間,但是這對(duì)于性能較差的低端機(jī)來說,可能是在災(zāi)難。這里直接如果識(shí)別到是低端機(jī),直接跳過動(dòng)畫。如果在3秒內(nèi)沒有加載完成,可以直接進(jìn)行兜底超時(shí)邏輯,展示兜底靜態(tài)圖。
輪播圖降級(jí)方案
針對(duì)低端機(jī)和弱網(wǎng)首屏引入的swiper.js,這里直接去掉swiper,使用css 手寫無限輪播動(dòng)畫。
通過上面的優(yōu)化動(dòng)作,針對(duì)低端機(jī)或者是弱網(wǎng)設(shè)備,我們的頁面也能夠快速的打開。
八、流渲染技術(shù)架構(gòu)升級(jí)
經(jīng)歷過上面一些常規(guī)性的優(yōu)化,想要首屏秒開進(jìn)一步提高,需要整體框架層面進(jìn)行架構(gòu)升級(jí)。 我們針對(duì)外投大流量頁面進(jìn)行了流渲染的架構(gòu)遷移。
流渲染的優(yōu)勢(shì)
- 渲染將頁面拆解為多個(gè)可獨(dú)立渲染的 “片段”(Fragment),服務(wù)端逐段生成 HTML 并流式傳輸給客戶端。例如,先返回頭部和主體框架,再逐步填充內(nèi)容模塊(如導(dǎo)航欄、列表項(xiàng)等)。
 - 用戶體驗(yàn)優(yōu)化:用戶無需等待整個(gè)頁面生成即可看到部分內(nèi)容,尤其是關(guān)鍵信息(如標(biāo)題、首屏圖文)的展示時(shí)間顯著縮短,提升 “感知速度”。
 - 性能數(shù)據(jù)對(duì)比:在復(fù)雜頁面中,流渲染可使首屏渲染時(shí)間(TTFB)減少 30%~50%,尤其適用于數(shù)據(jù)分批次加載的場(chǎng)景(如瀑布流、分頁內(nèi)容)。
 - 流渲染的分階段交互激活:流渲染可將頁面拆解為多個(gè) “可交互單元”,服務(wù)端在傳輸片段時(shí),同步或異步注入對(duì)應(yīng)的客戶端邏輯。
例如:先渲染商品列表的靜態(tài)結(jié)構(gòu),同時(shí)加載列表項(xiàng)的點(diǎn)擊事件邏輯,使首屏內(nèi)容在 hydration 完成前即可部分交互。結(jié)合增量 hydration(Incremental Hydration),僅對(duì)動(dòng)態(tài)更新的片段進(jìn)行交互激活,減少整體腳本執(zhí)行時(shí)間。提升頁面的 “可交互時(shí)間”(TTI,Time to Interactive),使用戶更早能與頁面互動(dòng)。 
歷史流量遷移
在流渲染遷移過程中,外投鏈接完成從非流渲染到流渲染的升級(jí)。
具體實(shí)施策略
- 新增頁面:直接使用新鏈接,原生支持流渲染技術(shù),享受性能優(yōu)化紅利。
 - 存量廣告計(jì)劃兼容:
 
- 已發(fā)布且無法修改鏈接的計(jì)劃:通過代理轉(zhuǎn)發(fā)機(jī)制,將原鏈接(cdn 域名)的請(qǐng)求回源到流渲染服務(wù),實(shí)現(xiàn) “鏈接不變、內(nèi)容由流渲染承載” 的無感知遷移。
 - 未發(fā)布的非流渲染鏈接計(jì)劃:聯(lián)合后端與產(chǎn)品團(tuán)隊(duì),通過數(shù)據(jù)批量處理(刷數(shù)),將原鏈接批量替換為流渲染鏈接,確保新計(jì)劃直接使用高性能架構(gòu)。
 
具體的架構(gòu)圖參考如下

apm性能腳本內(nèi)嵌
在流渲染頁面外投場(chǎng)景中,雖已實(shí)現(xiàn)部分頁面流渲染,但首屏秒開指標(biāo)提升效果不佳。通過對(duì)大盤數(shù)據(jù)深入剖析,發(fā)現(xiàn)接口響應(yīng)時(shí)間(RT)75 分位值約為 50ms,首字節(jié)時(shí)間(TTFB)75 分位值約為 500ms,由此可判斷服務(wù)端性能并非瓶頸所在。將分析方向轉(zhuǎn)向客戶端后,確認(rèn)首屏秒開的關(guān)鍵制約因素并非框架本身,而是監(jiān)控 SDK 腳本加載耗時(shí)。
具體而言,頁面首次有效繪制(FMP)的計(jì)算依賴于外部腳本 xxx.js。當(dāng)前機(jī)制下,頁面渲染時(shí)異步加載 xx.js,需等待該腳本加載完成后才能進(jìn)行 FMP 標(biāo)記計(jì)算,這導(dǎo)致 xx.js 加載耗時(shí)直接計(jì)入 FMP 統(tǒng)計(jì)??紤]到 xx.js 體積達(dá) 35KB,在首屏階段異步加載此腳本,對(duì)網(wǎng)絡(luò)條件較差的外投頁面性能影響顯著。
針對(duì)外投弱網(wǎng)場(chǎng)景,和APM團(tuán)隊(duì)提出首屏先采集后上報(bào)的需求,最終APM 團(tuán)隊(duì)提供了 7KB 的性能內(nèi)聯(lián)版本 SDK。在流渲染的的白屏階段同步加載 性能腳本JS,經(jīng)實(shí)踐驗(yàn)證,優(yōu)化效果顯著:在 4G 網(wǎng)絡(luò)環(huán)境下,F(xiàn)MP 指標(biāo)從優(yōu)化前的 1000ms 降至 500ms 左右,首屏秒開率提升約 25 個(gè)百分點(diǎn),提升十分顯著。
九、總結(jié)
在頁面的性能優(yōu)化過程中,結(jié)合流渲染的技術(shù)架構(gòu)升級(jí)、ISR、動(dòng)態(tài)加載非首屏組件、關(guān)鍵大圖預(yù)加載、Lottie 動(dòng)畫,以及針對(duì)低端設(shè)備的降級(jí)策略,可以形成一個(gè)多層次的優(yōu)化方案,為用戶提供流暢而快速的訪問體驗(yàn)。
通過這些優(yōu)化措施,外投頁面不僅能夠更好地滿足用戶需求,還能有效提高轉(zhuǎn)化率,為業(yè)務(wù)帶來更多機(jī)會(huì)。希望本文能夠幫助你在實(shí)際項(xiàng)目中更好地應(yīng)用這些性能優(yōu)化策略。















 
 
 








 
 
 
 