谷歌 Google I/O:提升Web核心性能指標(biāo)的九個(gè)建議
大家好,我是Echa。
不知道大家最近有沒(méi)有關(guān)注 2023谷歌 Google I/O 大會(huì)呢?作為小編的我最近也是非常重視,非常關(guān)心2023 谷歌 Google I/O 大會(huì)。作為程序員,一年一度的谷歌 Google I/O大會(huì)哪怕太忙也的了解了解,因?yàn)镚oogle I/O 大會(huì)太多太多的新技術(shù)和未來(lái)發(fā)展方向,有利于個(gè)人的未來(lái)規(guī)劃和學(xué)習(xí)方向。
今天繼續(xù)帶著大家解讀2023年 Google I/O ,我會(huì)重點(diǎn)為大家解讀前端開發(fā)者應(yīng)該關(guān)注的信息,應(yīng)該包括以下這些方向:
- 一、Web 平臺(tái)的最新動(dòng)態(tài)(已發(fā)布)
- 二、提升 Web 核心性能指標(biāo)優(yōu)化建議 (本篇)
- 三、準(zhǔn)備好迎接三方 Cookie 的終結(jié)
- 四、Web UI 開發(fā)的最新動(dòng)態(tài)
- 五、Web 動(dòng)畫開發(fā)的最新動(dòng)態(tài)
- 六、合作打造穩(wěn)定的 Web 體驗(yàn)
- 七、移動(dòng)端 Web 開發(fā)的新功能
Barry Pollard
Barry Pollard 本在文章中分享了 2023 年的最佳 Core Web Vitals 的優(yōu)化建議。Web 性能方面有非常多的建議,但很難判斷哪些建議會(huì)產(chǎn)生最大的影響。Chrome 團(tuán)隊(duì)花費(fèi)了一年的時(shí)間確定了每個(gè)核心 Web 指標(biāo)的三項(xiàng)最佳建議,這些建議對(duì)于大多數(shù)網(wǎng)站都是相關(guān)的,并且對(duì)于大多數(shù)開發(fā)人員來(lái)說(shuō)也是實(shí)際可行的。
LCP 優(yōu)化建議
首先,讓我們來(lái)看看網(wǎng)站最大內(nèi)容渲染時(shí)間(LCP)的建議。LCP 是渲染網(wǎng)頁(yè)最大內(nèi)容的時(shí)間,相比于 CLS 或 FID,LCP 往往是大多數(shù)網(wǎng)站最難以應(yīng)付的衡量指標(biāo)。
在大多數(shù)情況下,約 70-80% 的網(wǎng)站是因?yàn)樾枰秩净蛳螺d圖片引起的。去年的 Google I/O 活動(dòng)上,他們展示了實(shí)際的下載時(shí)間往往不是圖像的最大延遲,今年的分析進(jìn)一步證實(shí)了這一點(diǎn)。
Image 加載優(yōu)化
為了優(yōu)化 LCP 的時(shí)間,我們可以讓使靜態(tài) HTML 中的圖片資源更易于被發(fā)現(xiàn),這有可以讓瀏覽器的預(yù)加載掃描程序更早的找到并加載它。
使用背景圖片、客戶端渲染和懶加載等方法是可能存在問(wèn)題的,它們不利于 LCP 的發(fā)現(xiàn)。
而使用傳統(tǒng)的 img 元素或添加預(yù)加載鏈接等方式則可以使圖像資源被預(yù)加載掃描程序發(fā)現(xiàn),并被瀏覽器盡早加載。
你還可以使用 Chrome devtools 中的加載瀑布工具來(lái)識(shí)別開始加載較晚的資源,通過(guò)把圖片包含在 HTML 中(讓圖片元素預(yù)加載)即可解決這個(gè)問(wèn)題。但是在將 LCP 圖像優(yōu)化的可以被易于發(fā)現(xiàn)后,并不代表就可以更快的加載。因?yàn)闉g覽器更傾向于優(yōu)先處理阻塞渲染的內(nèi)容,如 CSS 和同步 JavaScript,而不是圖像。
fetch proirity API
新的 fetch proirity API 允許我們自定義標(biāo)記資源的優(yōu)先級(jí)。只需將 fetchprority 屬性添加到我們的圖像或預(yù)加載 LCP 元素中,就可以使瀏覽器更早地開始下載它們,并具有更高的優(yōu)先級(jí),這可以對(duì) LCP 時(shí)間產(chǎn)生很大的影響。這個(gè) API 已經(jīng)在基于 chromium 的瀏覽器中提供,Safari 和 Firefox 也正在實(shí)現(xiàn)相關(guān)代碼,并且這個(gè)屬性是漸進(jìn)式的,在不支持它的其他瀏覽器中會(huì)被簡(jiǎn)單地忽略。回到之前的例子,我們解決了圖片可盡早被發(fā)現(xiàn)的問(wèn)題,但是請(qǐng)求圖像和開始下載依然會(huì)存在很大的延遲。使用 fetch proirity API 可以將延遲最小化,并且讓圖像盡快下載。
這是一個(gè)優(yōu)化 LCP 指標(biāo)的最佳示例,我們還可以通過(guò)其他多種方式降低非關(guān)鍵資源的優(yōu)先級(jí)。
例如使用fetchprority=low 或者對(duì)它們進(jìn)行懶加載,以便按需獲取,這樣就可以讓瀏覽器集中處理更重要的資源,比如影響 LCP 指標(biāo)的元素。我們只需要確保不要在 LCP 圖像本身上使用這些技術(shù)即可。
如果我們使用了 JavaScript 框架,建議使用 Chrome Aurora 團(tuán)隊(duì)開發(fā)的 Image 組件添加圖像。其中 Angular 和 XJS 組件已經(jīng)內(nèi)置了提取優(yōu)先級(jí)的支持,團(tuán)隊(duì)也正在開發(fā) Next.js 的 Image 組件,以支持這個(gè)新的 API 。
Chrome 團(tuán)隊(duì)也與其他平臺(tái)有著合作,例如如果大家使用的是 WordPress,就可以嘗試使用官方 WordPress 性能實(shí)驗(yàn)室插件的新提取優(yōu)先級(jí)模塊。這是 Chrome 團(tuán)隊(duì)與 WordPress 核心性能團(tuán)隊(duì)開發(fā)合作的成果。
使用 CDN
前兩個(gè) LCP 的建議是和如何構(gòu)建 HTML 來(lái)讓 LCP 資源易于被發(fā)現(xiàn)以及優(yōu)先下載有關(guān),但這都取決于首屏加載 HTML 的速度。所以,最后一個(gè)建議是使用 CDN 來(lái)優(yōu)化 First Byte 的時(shí)間。
在瀏覽器收到第一次 HTML 請(qǐng)求響應(yīng)的第一個(gè)字節(jié)之前,網(wǎng)站是無(wú)法開始加載任何子資源的。越快將首節(jié)傳遞給瀏覽器,瀏覽器就可以越快地開始處理它,同時(shí)也可以讓其他所有的操作都更快的進(jìn)行。下面是兩個(gè)減少 ttfb 的最佳方法:
- (1)盡可能地將內(nèi)容服務(wù)器設(shè)置為地理位置更靠近用戶的位置來(lái)減少用戶與服務(wù)器之間的距離;
- (2)對(duì)內(nèi)容進(jìn)行緩存,以便最近請(qǐng)求的內(nèi)容可以快速再次提供。
內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)是執(zhí)行這兩個(gè)操作的最佳方法。CDN 是一組全球分布式的服務(wù)器,它作為用戶的連接點(diǎn)。由于最后一英里的傳輸速度往往是最慢的,而使用 CDN 可以盡可能的優(yōu)化這個(gè)問(wèn)題。CDN 還允許在這些邊緣節(jié)點(diǎn)上緩存內(nèi)容,從而進(jìn)一步降低加載時(shí)間,所以即使必須要返回到我們的源服務(wù)器進(jìn)行回源加載,CDN 通常也可以更快地完成。
開發(fā)者經(jīng)常使用 CDN 來(lái)托管靜態(tài)資源,如 CSS、JavaScript 或 Media 文件,但是通過(guò) CDN 提供 HTML 也可以獲得更多的好處。根據(jù) Web Almanac 的統(tǒng)計(jì)結(jié)果,只有 29% 的 HTML 文檔請(qǐng)求會(huì)通過(guò) CDN 服務(wù)加載。如果你不是這樣做的,那么這意味著你還有很大的機(jī)會(huì)來(lái)優(yōu)化網(wǎng)站的性能。
CLS 優(yōu)化建議
下面,我們來(lái)看看累積布局移位(CLS)的優(yōu)化建議。CLS 是網(wǎng)頁(yè)視覺(jué)穩(wěn)定性的度量指標(biāo),意味著當(dāng)有新的內(nèi)容加載時(shí),頁(yè)面的內(nèi)容是否經(jīng)常跳動(dòng)。
雖然 CLS 在 2020 年以來(lái)得到了很大的改進(jìn),但仍然有約四分之一的網(wǎng)站未達(dá)到推薦的閾值,所以很多網(wǎng)站在這方面還有很好的改進(jìn)用戶體驗(yàn)的機(jī)會(huì)。
內(nèi)容大小
第一個(gè) CLS 優(yōu)化建議是確保內(nèi)容能被顯式地縮放,當(dāng)它第一次被瀏覽器渲染時(shí),它就可以以正確的尺寸渲染。
一般情況下,我們都會(huì)熱衷于推薦大家設(shè)定圖像的寬度和高度的尺寸或 CSS 等效尺寸,現(xiàn)在這仍然是影響 CLS 的主要原因,網(wǎng)站也往往可以通過(guò)提供這些尺寸來(lái)輕松的優(yōu)化 CLS,但還有一些其他的優(yōu)化點(diǎn)。
比如我們可以通過(guò)新的 CSS aspect-ratio 屬性,就可以確保像視頻這樣的其他非圖像內(nèi)容也能夠較好的響應(yīng)。
另外還可以將渲染的文字設(shè)置適當(dāng)?shù)母叨?,例如使?nbsp;min-height 來(lái)為廣告卡片等動(dòng)態(tài)的內(nèi)容保留最小空間,空元素的默認(rèn)高度為零像素,所以即使對(duì)于某些動(dòng)態(tài)的內(nèi)容,我們不能確定實(shí)際的高度,也是可以通過(guò)使用 min-height 來(lái)減少 CLS 的影響。
BF Cache
我們?nèi)ツ昕吹?nbsp;CLS 的最大改進(jìn)之一是在 Chrome 中推出的回退緩存或 BF 緩存中。另外,Safari 和 Firefox 也已經(jīng)上線這個(gè)功能一段時(shí)間了。
一個(gè)頁(yè)面可能在初始加載時(shí)具有很大的 CLS ,因?yàn)殡S著其他內(nèi)容(如圖像和廣告)的加載,頁(yè)面的結(jié)構(gòu)會(huì)一直產(chǎn)生變化,從而影響 CLS。當(dāng)然,我們應(yīng)該盡量在首屏頁(yè)面渲染時(shí)避免加載這些內(nèi)容。
BF 緩存會(huì)在用戶離開之后,在內(nèi)存中存儲(chǔ)一個(gè)用戶加載頁(yè)面后的完整 CLS 快照。如果用戶返回了這個(gè)頁(yè)面,就會(huì)恢復(fù)這個(gè)快照。同樣的,如果用戶再次向前訪問(wèn),則也可以恢復(fù)這個(gè)快照。這就完全消除了任何 CLS 的加載,如果從頭開始重新渲染頁(yè)面,BF 緩存也會(huì)默認(rèn)啟用,我們不需要采取任何措施來(lái)主動(dòng)啟用它,但是我們可以使用某些 API 阻止瀏覽器使用它,但這可能會(huì)導(dǎo)致瀏覽器沒(méi)辦法更好的響應(yīng),建議大家不要放棄這種免費(fèi)的性能優(yōu)化方案。
Chrome DevTools 有一個(gè)工具,可以讓我們測(cè)試頁(yè)面是否有使用 BF Cache 的資格。如果沒(méi)辦法使用 BF Cache ,工具一般都會(huì)告訴我們具體原因。最常見的原因是我們?cè)O(shè)定了 cache-control 這個(gè) Header 的值為 no-storage或者在頁(yè)面中使用了 unload handler,這兩者都會(huì)阻止 BF Cache 的使用。
在 Lighthouse 10 中,也添加了一個(gè)類似的檢測(cè)能力,也可以解釋頁(yè)面不符合資格的原因。
BF Cache 是 Chrome 團(tuán)隊(duì)為了讓網(wǎng)頁(yè)瀏覽更快的正在開發(fā)的一系能力之一,這個(gè)領(lǐng)域還有一些其他的能力,比如預(yù)加載和預(yù)渲染也是可以改善網(wǎng)站 CLS 指標(biāo)的。
動(dòng)畫和轉(zhuǎn)換的處理
最后一個(gè) CLS 建議是處理動(dòng)畫和轉(zhuǎn)換。動(dòng)畫通常用于移動(dòng)端的內(nèi)容,如 cookie banner 或從頂部或底部滑入的其他通知橫幅,者具體取決于這些動(dòng)畫或過(guò)渡是怎么編碼的,它們可以更少或者更有效,并且可以幫助優(yōu)化 CLS。
動(dòng)畫的渲染需要瀏覽器重新布局頁(yè)面,因此需要更多的工作,即使脫離正常文檔流的絕對(duì)定位元素,例如使用 top 或 left 移動(dòng)內(nèi)容,也會(huì)將其計(jì)算為布局移位,即使它不會(huì)移動(dòng)任何周圍其他的內(nèi)容,內(nèi)容本身也在移動(dòng),并且有可能影響其他內(nèi)容,所以這也會(huì)影響 CLS。
使用 translate 進(jìn)行相同的動(dòng)畫不會(huì)在瀏覽器的布局處理中移動(dòng)內(nèi)容,而是在合成器層中進(jìn)行的,除了對(duì)于瀏覽器來(lái)說(shuō)工作量較小之外,這還意味著它無(wú)法影響其他的內(nèi)容,這也意味著它對(duì) CLS 的影響就變小了。所以我們的解決方案就是替換使用 top 或 left 的動(dòng)畫,并且這種方式在所有的瀏覽器中都得到了支持。
始終優(yōu)先使用復(fù)合動(dòng)畫,比如如 transform ,而不是圖層誘導(dǎo)的非復(fù)合動(dòng)畫,如更改 top、right、bottom 和 left。
并且 Lighthouse 也有一個(gè)相關(guān)的能力來(lái)識(shí)別這些問(wèn)題。
FID 優(yōu)化建議
最后我們來(lái)看看用戶響應(yīng)相關(guān)的優(yōu)化建議,這包括用戶和頁(yè)面進(jìn)行首次交互操作所花費(fèi)的時(shí)間(FID),以及更全面的交互到下一次繪制的時(shí)間(INP)。
網(wǎng)站響應(yīng)性的關(guān)鍵在于確保不阻塞主線程,因?yàn)檫@會(huì)導(dǎo)致瀏覽器無(wú)法響應(yīng)用戶輸入。
分解長(zhǎng)任務(wù)
第一個(gè)建議是識(shí)別并分解長(zhǎng)任務(wù),相當(dāng)于給瀏覽器一些喘息的空間,以便它能夠響應(yīng)用戶輸入。
Chrome Devtools和 Lighthouse 將長(zhǎng)任務(wù)定義為需要 50 毫秒或更長(zhǎng)時(shí)間的渲染工作。這可能聽起來(lái)不是很多,但在瀏覽器術(shù)語(yǔ)中,這可以是網(wǎng)站能感覺(jué)到比較好的響應(yīng)或不響應(yīng)的區(qū)別。
JavaScript 是單線程且貪婪的,一旦它占用了 CPU,它就會(huì)盡可能地一直保持它,直到它不能處理或者處理完畢為止。在這個(gè)例子中,即使有五個(gè)子進(jìn)程,所有的五個(gè)進(jìn)程也是會(huì)一個(gè)接一個(gè)地執(zhí)行。所以,在我們的代碼中放置一些斷點(diǎn)就是關(guān)鍵了。
我們可以使用設(shè)置超時(shí) settimeout 0 毫秒延遲來(lái)放入非關(guān)鍵的工作和新的任務(wù),這些新任務(wù)就會(huì)在已經(jīng)排隊(duì)的任何任務(wù)之后執(zhí)行。
還有一些新的和即將推出的瀏覽器 API ,如 isInputPending、scheduler.postTask 和 scheduler.yield,它們可以幫助大家決定何時(shí)以及如何放棄主線程。有關(guān)更多詳細(xì)的信息,可以去看 web.dev 上優(yōu)化長(zhǎng)任務(wù)的相關(guān)文章 :https://web.dev/optimize-long-tasks/ 。另外,在 Google I/O 上,還有一個(gè)專門關(guān)于優(yōu)化長(zhǎng)任務(wù)的獨(dú)立演講。
去除不必要的 JS
盡管優(yōu)化我們頁(yè)面上的 JavaScript 代碼執(zhí)行是一個(gè)不錯(cuò)的方法,但更好的方式是一開始就不要發(fā)送太大的 JavaScript。
現(xiàn)在的網(wǎng)站上加載的 JavaScript 越來(lái)越大了,但我們需要重新檢查一下有這些 JavaScript 是否都是必要的。
我們可以使用 Chrome Devtools 的 Coverage 特性來(lái)查看我們的 JavaScript 有多少被執(zhí)行了。如果在頁(yè)面加載期間沒(méi)有使用的大部分 JavaScript ,都可以考慮進(jìn)行代碼分離以在需要時(shí)或?yàn)g覽器不太繁忙的時(shí)候加載這些代碼。
Aurora 團(tuán)隊(duì)還開發(fā)了一個(gè) xjs 腳本組件,允許我們加載較少且關(guān)鍵的第三方代碼,并采用各種策略來(lái)減少這些腳本的影響。標(biāo)簽管理器是另一個(gè)容易積累舊 JavaScript 代碼的地方,這些代碼可能不再需要了。定期檢查我們的標(biāo)簽,以確保刪除所有標(biāo)簽,因?yàn)榧词顾鼈儾辉儆|發(fā),它們?nèi)匀恍枰螺d、解析和編譯。
避免大型渲染更新
改善響應(yīng)性的最后一個(gè)建議是避免大型渲染更新。JavaScript 不是唯一可以影響我們網(wǎng)站響應(yīng)性的東西,如果瀏覽器需要大量的工作來(lái)將頁(yè)面渲染到屏幕上,那么瀏覽器本身也可能會(huì)變慢。大型渲染更新可能會(huì)在有大量Dom 更改時(shí)發(fā)生,無(wú)論是有意還是由于一個(gè)更改導(dǎo)致許多其他元素需要重新計(jì)算。避免大型渲染更新的最佳方法是保持較小的 Dom 結(jié)構(gòu),以便即使存在關(guān)聯(lián)效應(yīng),也可以快速處理它們。
我們還有一個(gè) Lighthouse 審計(jì)工具來(lái)幫助大家實(shí)現(xiàn)這一目標(biāo)。
CSS containment 是另一種分離網(wǎng)頁(yè)區(qū)域的方法,它可以告訴瀏覽器某些區(qū)域中的元素可以不受其他區(qū)域更改的影響,從而減少布局的工作。
content-visibility 是 CSS containment 的一種擴(kuò)展能力,允許我們能完全跳過(guò)離屏內(nèi)容的布局和渲染。
最后,大家應(yīng)該避免濫用 requestAnimationFrame API,它應(yīng)應(yīng)該只用于關(guān)鍵的渲染工作,如果通過(guò)這個(gè) API 安排了過(guò)多的工作,它會(huì)導(dǎo)致渲染變慢。
這些就是我們認(rèn)為大家首先應(yīng)考慮的九個(gè)改善網(wǎng)站核心性能指標(biāo)的優(yōu)化建議。這并不是一個(gè)明確的列表,而是我們的研究表明可以真正提高大家網(wǎng)站性能的幾個(gè)更有影響力的選項(xiàng)。包括 Chrome Devtools、Lighthouse 和我們添加到 JavaScript 框架和平臺(tái)中的組件,許多這些建議已經(jīng)涵蓋在我們的各種工具中。但我們并沒(méi)有放松警惕,并且也在一直更新我們的工具和文檔,來(lái)呈現(xiàn)這些關(guān)鍵建議。