日本电影一区二区_日本va欧美va精品发布_日本黄h兄妹h动漫一区二区三区_日本欧美黄色

落地頁性能進化之路(落地頁系統(tǒng))

信息流投放是公司獲取公域流量的關(guān)鍵渠道,也是公司外部流量的主要來源。而投放落地頁會作為這個流量鏈路的第一步最先映入用戶眼簾。因此落地頁整體的加載體驗和交互體驗變成了影響用戶轉(zhuǎn)化的重要因素。

摘自Google對于“核心網(wǎng)頁指標(biāo)”的報告:

為什么網(wǎng)頁性能很重要

研究表明,更好的核心網(wǎng)頁指標(biāo)可以提高用戶互動度和業(yè)務(wù)指標(biāo)。例如:

研究表明,當(dāng)網(wǎng)站達到核心網(wǎng)頁指標(biāo)閾值時,用戶放棄加載網(wǎng)頁的可能性會降低 24%。

Largest Contentful Paint (LCP) 每減少 100 毫秒,Farfetch 的網(wǎng)站轉(zhuǎn)化率就會提高 1.3%。

我們當(dāng)前的眾多落地頁都是由低代碼平臺搭建出來的,在前期投放過程中暴露出了許多性能及交互問題,譬如首頁白屏、異步組件加載耗時等。

從兩個比較關(guān)鍵的加載性能指標(biāo)來看,當(dāng)前頁面的中位數(shù)FCP超過1500ms,中位數(shù)LCP超過4000ms,而對比業(yè)界標(biāo)準(zhǔn),達到優(yōu)秀級別的數(shù)據(jù)是FCP低于1000ms,LCP低于2500ms,顯然有著不小的差距。那針對落地頁,我們也會以最低達到這個標(biāo)準(zhǔn)為目標(biāo)去拆解優(yōu)化,同時在頁面內(nèi)的交互上也需要優(yōu)化細節(jié)。

下面就來分享下整個優(yōu)化動作是如何進行的。

拆解分析

一個性能表現(xiàn)不佳的Web頁面,通過對Lighthouse及Performance的分析,結(jié)合加載時序圖,已經(jīng)可以找出90%的問題了,這里我們先來看一張對應(yīng)當(dāng)前頁面的簡易時序圖:

落地頁性能進化之路(落地頁系統(tǒng))

結(jié)合整個項目代碼來分析(具體的代碼邏輯比較分散,這里就不貼出來了),大致總結(jié)為如下六個問題點:

1、針對DNS、TCP以及TLS連接,當(dāng)前代碼無任何優(yōu)化邏輯,這一塊兒大有可為;

2、JS/CSS靜態(tài)資源文件存在單個文件過大的問題(Gzip前超過500KB);

3、靜態(tài)資源包存在重復(fù)引用問題;

4、在觸發(fā)FCP及LCP之前是否可以避免XHR請求的阻塞?

5、FCP完全可以在HTML加載完畢后就觸發(fā),而不應(yīng)該在靜態(tài)資源及XHR請求之后;

6、圖片及組件仍有優(yōu)化空間:異步組件、圖片壓縮并轉(zhuǎn)為webp、圖片預(yù)加載。

以常規(guī)思路針對每個具體的問題去做分析可能會得到以下辦法,比如:

1、通過SSR/SSG來解決XHR請求阻塞和靜態(tài)資源加載阻塞問題;

2、通過依賴分析及合理分包方案來解決靜態(tài)資源文件問題;

3、通過預(yù)連接解決網(wǎng)絡(luò)連接耗時;

4、通過預(yù)加載解決異步組件以及大圖片的加載耗時。

實際優(yōu)化過程:

除了重構(gòu)為SSR外,其他方案相對來說成本更低,也更易實施,于是乎我們先應(yīng)用相對更常規(guī)的方案,吭哧吭哧優(yōu)化完畢后,加載數(shù)據(jù)表現(xiàn)也基本快達到我們設(shè)立的目標(biāo)了,但是XHR請求和靜態(tài)文件的阻塞仍然沒有解決,頁面還存在白屏,用戶實際體感上還是有缺陷,最后就不得不考慮令人頭痛的SSR重構(gòu)了……

接下來針對上述問題,我這里來逐一拆解并詳細分析,看看最后是如何達到滿意的效果的。

工程構(gòu)建

這里主要是為了解決拆解分析中提到的第2點、第3點。

1、依賴分析

這部分的第一件事情就是打開依賴分析,每次有比較大的變動都先在開發(fā)環(huán)境看看依賴分析,加載進來的東西是否合理,做到心中有數(shù)。

不管是Vite還是Webpack,都有對應(yīng)的工具,比如Webpack的webpack-bundle-analyzer可視化工具,通過可視化界面以及生成的stats.json,我們就可以進行逐一分析和優(yōu)化了。

落地頁性能進化之路(落地頁系統(tǒng))

2、重復(fù)依賴

這里落地頁通過上面的依賴分析就發(fā)現(xiàn)了一個很明顯的問題:

低代碼平臺組件庫的一些組件的dependencies都寫了相同的依賴包,導(dǎo)致npm i的時候,這些依賴被重復(fù)安裝并且被重復(fù)打包:

落地頁性能進化之路(落地頁系統(tǒng))

最簡單的方法就是去掉子組件的dependencies,將依賴寫在最外層,當(dāng)然也有更優(yōu)雅的方法去處理,這里處理掉重復(fù)依賴后,生產(chǎn)環(huán)境的靜態(tài)文件少了100KB 。

這里只是其中的一個實例,借助這個工具,同學(xué)們也能更輕松的發(fā)現(xiàn)一些其他的未知問題。

3、合理分包

關(guān)于分包,構(gòu)建工具會有自己的一套默認(rèn)策略,但是如果想做到極致,必然是需要針對具體的業(yè)務(wù)場景做定制化配置的。

針對落地頁,我制定了一個分包原則,然后根據(jù)這個原則去做細化配置:

前端框架- UI庫 – 核心工具庫 – 同步組件 – 異步組件 – 跟隨默認(rèn)策略

詳細的配置這里就不貼出來了,以Webpack為例就是利用splitChunks配合正則提前配置好分割參數(shù),而其中異步組件的分割則是配合import()方法來實現(xiàn)的,這一塊兒在后面會有詳細的介紹。

下圖是做了細化的分包后,npm run bUIld的靜態(tài)文件列表:

落地頁性能進化之路(落地頁系統(tǒng))

實際上這個列表中的絕大部分文件都是根據(jù)頁面交互按需加載的(也就是上面提到的異步組件分割),保證了在首頁只加載必要內(nèi)容。同時之前存在的單個大文件(單文件超500KB)也被拆分為多個小文件,圖中可以看到Gzip后,最大的文件不超過100KB。

根據(jù)瀏覽器的6個TCP連接并發(fā)限制,在HTTP1.1時代你可能覺得這是個負(fù)優(yōu)化,因為那時候還流行CSS雪碧圖呢,也是為了降低并發(fā)數(shù)。但是HTTP2.0的優(yōu)勢在這種情況下卻可以得到比較好的發(fā)揮,從落地頁這邊實際實驗對比下來,正常網(wǎng)絡(luò)環(huán)境加載單個大文件(800KB左右)比加載5個小文件要慢5%左右,如果是弱網(wǎng)環(huán)境,差距會更明顯一些。

更重要的,單個大文件不利于緩存管理,一些常年不咋動的模塊,比如上面分包原則中的前端框架 、UI庫 、核心工具庫 ,這些都是屬于迭代頻率很低的,單獨拆出能有效利用緩存。

如果有同學(xué)覺得自己的頁面加載表現(xiàn)不佳,同樣可以嘗試借鑒上面的思路去做優(yōu)化。

預(yù)連接、預(yù)加載

拆解分析的第1點、第6點都會在下面的動作中得以優(yōu)化。

1、預(yù)連接

預(yù)連接顧名思義就是預(yù)先建立網(wǎng)絡(luò)連接,這其中包括DNS、TCP、TLS,當(dāng)后續(xù)請求該域名資源時,可直接使用已建立好的連接。所以需要在比較關(guān)鍵的節(jié)點上使用,比如:JS文件域名、主圖片域名、第三方重要的SDK。

當(dāng)前可用方法為:

  • dns-Prefetch,預(yù)先對指定域名進行DNS解析。
  • preconnect,預(yù)先建立所有連接,包括DNS、TCP、TLS。

這兩個都是HTML特性,落地頁這邊是兩個一起配合使用,在preconnect不支持的時候,以dns-prefetch來提供降級:

落地頁性能進化之路(落地頁系統(tǒng))落地頁性能進化之路(落地頁系統(tǒng))

在上圖落地頁實際Connection View的表現(xiàn)中,可以很直觀的看到,在preconnect的作用下,實際資源請求之前,TCP和TLS連接已經(jīng)被預(yù)先建立了。

這塊兒的時間會被直接節(jié)省掉,這還是在有DNS緩存的情況下,如果是新用戶沒有DNS緩存,那由于DNS延遲帶來的時間節(jié)省將會更多。

2、預(yù)加載

預(yù)連接是建立連接但不加載,而預(yù)加載是加載但不執(zhí)行,目前主要用到的是prefetch和preload特性。

2.1、prefetch、preload

– preload提示瀏覽器以更高的優(yōu)先級立即加載靜態(tài)資源并緩存,以期在后續(xù)使用時候無需等待,在瀏覽器中的Priority標(biāo)識為High

– prefetch提示瀏覽器未來可能會使用到的某個資源,瀏覽器就會在閑時去加載對應(yīng)資源并緩存,在瀏覽器中的Priority標(biāo)識為Lowest,是優(yōu)先級最低的

可見preload適合馬上需要用到的資源,或者說是當(dāng)前頁面中的重要資源,以此來提高它們的加載優(yōu)先級,落地頁中,在body標(biāo)簽之前,我們將首頁需要的JS文件都設(shè)置了preload,這樣在body標(biāo)簽開始渲染之前,JS已經(jīng)開始加載了,同時不阻塞后續(xù)標(biāo)簽的解析執(zhí)行,有點類似于script標(biāo)簽的defer屬性。

落地頁性能進化之路(落地頁系統(tǒng))落地頁性能進化之路(落地頁系統(tǒng))

這里對一張主背景圖使用了preload,并且通過fetchPriority將其優(yōu)先級調(diào)整到了High,下面這張圖就可以看出使用和不使用“提取優(yōu)先級”的區(qū)別,使用preload并且將優(yōu)先級設(shè)置為High后,LCP 時間從 2.6 秒縮短到 1.9 秒。

落地頁性能進化之路(落地頁系統(tǒng))

上面講的都是關(guān)于preload的,那prefetch的應(yīng)用場景在哪里?來看看它和異步組件的配合吧。

2.2、如何將預(yù)加載應(yīng)用到異步組件

落地頁性能進化之路(落地頁系統(tǒng))

首先該組件會在打包時被分割為單獨的名為“CmsLayerGradeTabSelector”的JS文件。

上面的webpackPrefetch注釋會被webpack翻譯為對應(yīng)的rel="prefetch"的link標(biāo)簽。也就意味著該文件會被瀏覽器在空閑時加載并緩存,當(dāng)交互觸發(fā)異步組件的時候,直接去緩存中取文件。

如果不加webpackPrefetch,JS文件會按需加載,也就是交互觸發(fā)的時候才加載,進而帶來的就是交互體驗問題了。

2.3、精確控制加載時機

落地頁性能進化之路(落地頁系統(tǒng))

通過上面的代碼,在實際場景中,我們可以任意時刻控制某個資源的預(yù)加載和執(zhí)行。比如你知道接下來將會播放一個視頻、渲染一張大圖,都可以預(yù)先加載它們。

由低代碼平臺引出的問題

上述步驟全部優(yōu)化完畢后,整體效果提升也比較明顯,測得線上的FCP和LCP已經(jīng)比較接近設(shè)立的目標(biāo)了:FCP低于1000ms,LCP低于2500ms,但是由于XHR和靜態(tài)資源的阻塞仍未解決,在文章開篇也提到了,這里會導(dǎo)致白屏,用戶體感不佳,如果能解決這個,那整體表現(xiàn)會再上一個臺階。

最后針對第4點、第5點,我們發(fā)現(xiàn)問題其實是由低代碼平臺引出的,低代碼平臺在出碼后,直接將內(nèi)容存到后端,前端需要根據(jù)對應(yīng)頁面ID去即時獲取頁面內(nèi)容以及業(yè)務(wù)數(shù)據(jù)。這樣會直接導(dǎo)致首頁的白屏,因為即使是在靜態(tài)資源完全加載完畢后,仍然需要調(diào)用接口獲取頁面數(shù)據(jù),而后才能開始渲染頁面。

分析下來,其實這里如果能做到頁面數(shù)據(jù)的靜態(tài)化而非即時拉取,就可以完全解決問題。

SSR

最先想到的可能是將頁面由CSR重構(gòu)為SSR,可以完全解決掉靜態(tài)資源以及XHR請求問題,但是因為當(dāng)前頁面依托于低代碼平臺,且已經(jīng)迭代了多次。重構(gòu)會涉及到整個B端,低代碼平臺邏輯復(fù)雜,評估下來的開發(fā)成本很高。同時大流量的投放頁面,采用SSR對服務(wù)器要求很高,可能需要大量堆疊機器才能保證性能,這塊兒又會增加支出。

數(shù)據(jù)靜態(tài)化

退一步想,結(jié)合SSR的優(yōu)點,如果能將XHR請求相關(guān)的頁面數(shù)據(jù)預(yù)先放在HTML里面,通過HTML直出,就能以最快速度拿到頁面數(shù)據(jù)及結(jié)構(gòu)了,相比SSR來說,就只多了靜態(tài)資源的加載,而在靜態(tài)資源加載之前,我們同樣也能干很多事情。

頁面如何靜態(tài)化?

1、靜態(tài)化改造

一個合格的低代碼平臺完全可以做到這一點,首先看一下沒有靜態(tài)化的頁面生成流程:

落地頁性能進化之路(落地頁系統(tǒng))

從這張圖可以就看出問題了,C端在通過XHR請求拿到JSON Schema的那一刻才能開始渲染動作,這里需要做的是讓JSON Schema數(shù)據(jù)以靜態(tài)形式存儲在HTML中。在Nginx以及服務(wù)端做一些動作可以很好的去實現(xiàn)這個想法:

落地頁性能進化之路(落地頁系統(tǒng))

對比起來發(fā)現(xiàn)流程復(fù)雜了不少:

每次B端發(fā)布一個頁面,服務(wù)端會從輕舟容器中取出原始HTML,并且將JSON Schema通過script標(biāo)簽嵌入到HTML中,隨后標(biāo)記上對應(yīng)的projectId存儲到OSS中。

C端HTML請求會被Nginx轉(zhuǎn)發(fā)到后端服務(wù),后端取出對應(yīng)的拼接好的HTML返回給前端。

落地頁性能進化之路(落地頁系統(tǒng))

到了這一步,我們已經(jīng)做到了數(shù)據(jù)靜態(tài)化,從而節(jié)省掉了靜態(tài)資源加載、XHR請求獲取JSON Schema這兩個非常耗時的步驟,提前拿到了頁面數(shù)據(jù),畫一個簡易的Waterfall來看看區(qū)別:

落地頁性能進化之路(落地頁系統(tǒng))

靜態(tài)化之后,F(xiàn)irst Contentful Paint在HTML加載完畢后就會發(fā)生,而且是一次有效的內(nèi)容繪制,因為我們已經(jīng)知曉頁面內(nèi)容了。

2、提前繪制

接上一節(jié),在知曉頁面結(jié)構(gòu)和數(shù)據(jù)的情況下,如何才能更快更全的渲染出必要內(nèi)容,用以留住用戶,現(xiàn)階段我們沒有JS和CSS,所以只能在Body中寫簡易邏輯來處理JSON Schema,展示出關(guān)鍵內(nèi)容:

落地頁性能進化之路(落地頁系統(tǒng))

落地頁性能進化之路(落地頁系統(tǒng))

通過上面的處理,借助頁面數(shù)據(jù)中的base64格式頭圖,幾乎立即就能展示出頁面的頭圖、課程信息、詳情圖等關(guān)鍵內(nèi)容,這時候用戶已經(jīng)可以進行瀏覽了,剩余的完整內(nèi)容只需要等待靜態(tài)文件的加載就行了。

處理完畢后的頁面表現(xiàn),清掉緩存,在正常的無線網(wǎng)絡(luò)環(huán)境下,視覺感受幾乎是秒開:

落地頁性能進化之路(落地頁系統(tǒng))

如果想在這個時機展示更多內(nèi)容,我們也可以自由拓展,這里是非常靈活的。

到這里拆解分析中的第5點、第6點就被完全解決了,總結(jié)一下:

對于一個成熟的平臺,頁面的靜態(tài)化處理肯定是必須的,可以是各種其他的處理形式,借鑒SSR、SSG、ISR等各種渲染方案的優(yōu)勢,來做到最大化貼合自己的業(yè)務(wù)。

這個思路其實同樣也適用于一些小的站點,因為改造成本其實并不高:利用好OSS、改造一下后端存儲邏輯、增加一個接口即可實現(xiàn)。

最后

落地頁在做完這些優(yōu)化后,線上中位數(shù)FCP從1500ms縮短到了500ms ,LCP從4000ms 縮短到2000ms。

優(yōu)化完至今已經(jīng)穩(wěn)定運行了一段時間,而針對當(dāng)前現(xiàn)狀仍然還有一個可以優(yōu)化的點

當(dāng)前針對落地頁靜態(tài)化后的HTML,由于考慮到頁面版本控制、緩存問題、以及線上的業(yè)務(wù)對各業(yè)務(wù)線有不同的域名要求,是由Nginx轉(zhuǎn)發(fā)到后端接口再去OSS獲取的,后續(xù)針對一些特殊的對域名要求寬松、變動頻率低的業(yè)務(wù)場景,可以考慮直接申請CDN域名,通過CDN域名投放。這樣就省掉了Nginx、后端服務(wù)的兩層處理帶來的時間損耗。

整篇文章涉及到的大部分優(yōu)化都是比較通用的手段,能帶來實打?qū)嵉奶嵘?,但在實際開發(fā)中經(jīng)常被很多同學(xué)忽略,其實在項目立項之初,就應(yīng)該提前考慮好大致的代碼組織架構(gòu)、可以實現(xiàn)的常規(guī)以及非常規(guī)優(yōu)化方案,避免在后期再來分析優(yōu)化從而帶來更高額的成本。

作者:胡斌

來源-微信公眾號:高途技術(shù)

出處:https://mp.weixin.qq.com/s/yjEnfe_RTTAMP2bAaAXLxA

相關(guān)新聞

聯(lián)系我們
聯(lián)系我們
公眾號
公眾號
在線咨詢
分享本頁
返回頂部
缙云县| 大足县| 尼玛县| 巴青县| 宝兴县| 礼泉县| 石棉县| 广平县| 湾仔区| 田阳县| 舟曲县| 疏附县| 万宁市| 萨迦县| 深州市| 四子王旗| 桑日县| 长武县| 雷山县| 兴隆县| 诸暨市| 青岛市| 仙桃市| 治县。| 沈丘县| 安阳市| 宁德市| 宣城市| 汤阴县| 涿州市| 三江| 铁力市| 同江市| 维西| 平潭县| 奉贤区| 永新县| 阿尔山市| 吉安市| 前郭尔| 隆德县|