瞭解如何最佳化網站的 Interaction to Next Paint。
Interaction to Next Paint (INP) 是穩定的 Core Web Vitals 指標,可評估網頁回應使用者互動的整體效能,方法是觀察使用者造訪網頁期間,網頁對所有符合資格的互動的延遲時間。最終 INP 值是指觀測到的最長互動時間 (有時會忽略離群值)。
為了提供良好的使用者體驗,網站應力求 Interaction to Next Paint 為 200 毫秒以下。為確保多數使用者都能享有此等級的體驗,建議您以網頁載入的第 75 個百分位數做為門檻,並區分行動裝置和電腦裝置。
視網站而定,互動可能很少,甚至完全沒有,例如網頁主要由文字和圖片組成,互動元素很少或完全沒有。或者,如果是文字編輯器或遊戲等網站,可能會有數百或數千個互動。無論是哪種情況,如果 INP 過高,使用者體驗就會受到影響。
改善 INP 需要花費時間和心力,但成效是提供更優質的使用者體驗。本指南將說明改善 INP 的方法。
找出導致 INP 不佳的原因
您必須先取得資料,才能判斷網站的 INP 是否不佳或需要改善,進而修正互動速度緩慢的問題。取得這些資訊後,您就可以進入實驗室,開始診斷互動速度緩慢的問題,並找出解決方法。
找出現場的互動速度緩慢問題
在理想情況下,您應先從實地資料開始,盡可能提升 INP。實境使用者監控 (RUM) 供應商提供的欄位資料,不僅可提供網頁的 INP 值,還可提供情境資料,指出哪些特定互動導致 INP 值,以及互動是否發生在網頁載入期間或之後、互動類型 (點擊、按鍵或輕觸) 等其他重要資訊。
如果您不依賴 RUM 供應商取得現場資料,INP 現場資料指南建議透過 PageSpeed Insights 使用 Chrome 使用者體驗報告 (CrUX),以便填補空白。CrUX 是 Core Web Vitals 計畫的官方資料集,提供數百萬個網站 (包括 INP) 的指標概要。不過,CrUX 通常不會提供您從 RUM 供應商取得的背景資料,以利分析問題。因此,我們仍建議網站盡可能使用 RUM 供應商,或實作自己的 RUM 解決方案,以補足 CrUX 提供的功能。
在實驗室中診斷互動速度緩慢的問題
理想情況下,您應該在取得顯示互動速度緩慢的實地資料後,才開始在實驗室進行測試。在沒有實地資料的情況下,您可以採用一些策略,在實驗室中找出互動速度緩慢的問題。這類策略包括追蹤常見的使用者流程並測試互動情形,以及在載入期間與網頁互動 (此時主執行緒通常最繁忙),以便在使用者體驗的關鍵部分顯示互動速度緩慢的問題。
改善互動
找出互動速度緩慢的問題後,如果您可以在實驗室中手動重現問題,下一步就是進行最佳化。互動可分為三個階段:
- 輸入延遲時間:從使用者開始與網頁互動開始計算,結束時間則是互動事件回呼開始執行時。
- 處理時間,包括事件回呼執行至完成所需的時間。
- 呈現延遲,即瀏覽器呈現下一個影格所需的時間,其中包含互動內容的視覺結果。
這三個階段的總和就是總互動延遲時間。互動過程的每個階段都會對總互動延遲時間造成影響,因此請務必瞭解如何最佳化互動的各個部分,讓互動執行時間盡可能縮短。
找出並減少輸入延遲
當使用者與網頁互動時,第一個互動部分是輸入延遲時間。視網頁上的其他活動而定,輸入延遲時間可能會相當長。這可能是因為主執行緒上發生的活動 (可能因載入、剖析和編譯指令碼)、擷取處理、計時器函式,甚至是其他快速連續發生且彼此重疊的互動所致。
無論互動輸入延遲的來源為何,您都應盡可能減少輸入延遲,讓互動盡快開始執行事件回呼。
指令碼評估與啟動期間的長時間工作之間的關係
頁面生命週期中互動性的關鍵部分是啟動期間。網頁載入時會先進行轉譯,但請務必記住,即使網頁已轉譯,也不代表網頁已完成載入。視網頁需要多少資源才能完全運作而定,使用者可能會在網頁載入期間嘗試與網頁互動。
指令碼評估是會延長互動輸入延遲時間的因素之一。從網路擷取 JavaScript 檔案後,瀏覽器仍須執行一些工作,才能執行 JavaScript,這些工作包括剖析指令碼以確保其語法有效、將其編譯為位元碼,然後執行。
視指令碼大小而定,這項工作可能會在主執行緒上引入長時間的工作,導致瀏覽器延遲回應其他使用者互動。為了讓網頁在載入期間能回應使用者輸入內容,請務必瞭解如何減少在網頁載入期間執行長時間任務的可能性,以便讓網頁保持快速回應。
最佳化事件回呼
輸入延遲時間只是 INP 測量結果的第一部分。您也必須確保在回應使用者互動時執行的事件回呼,可以盡快完成。
經常讓出主執行緒
在最佳化事件回呼時,最佳的一般建議是盡量減少回呼中的工作量。不過,互動邏輯可能很複雜,您可能只能稍微減少互動邏輯的工作量。
如果發現您的網站也是這種情況,下一個可嘗試的方法,就是將事件回呼中的作業拆解為個別工作。這可避免集體工作變成長時間的工作,進而阻斷主執行緒,讓其他互動 (原本會等待主執行緒執行) 更快執行。
setTimeout
是分割工作的方式之一,因為傳遞至該函式的回呼會在新工作中執行。您可以單獨使用 setTimeout
,或將其用途抽象化為個別函式,以便更符合人體工學。
雖然隨意產生產量比完全不產生產量好,但有更精細的方式可產生主要執行緒,只需在更新使用者介面的事件回呼後立即產生產量,即可讓算繪邏輯更快執行。
產生收益,讓轉譯工作提早進行
更進階的讓步技巧包括在事件回呼中建構程式碼,以便限制執行的內容,只限於為下一個影格套用視覺更新所需的邏輯。其他所有內容都可以延後至後續工作。這不僅可讓回呼輕巧靈活,還可改善互動顯示時間,因為系統不會允許視覺更新阻斷事件回呼程式碼。
舉例來說,假設有個富文字編輯器,會在您輸入文字時設定文字格式,並根據您輸入的內容更新 UI 的其他部分 (例如字數、醒目顯示拼字錯誤,以及其他重要的視覺回饋)。此外,應用程式可能也需要儲存您輸入的內容,以免您離開應用程式後,無法繼續編輯內容。
在這個範例中,系統需要根據使用者輸入的字元執行下列四項操作。不過,您只需要在下一個影格顯示前完成第一個項目。
- 將使用者輸入的內容更新至文字方塊,並套用任何必要的格式設定。
- 更新 UI 中顯示目前字數的部分。
- 執行邏輯,檢查拼寫錯誤。
- 儲存最新變更 (在本機或遠端資料庫中)。
執行這項操作的程式碼可能會如下所示:
textBox.addEventListener('input', (inputEvent) => {
// Update the UI immediately, so the changes the user made
// are visible as soon as the next frame is presented.
updateTextBox(inputEvent);
// Use `setTimeout` to defer all other work until at least the next
// frame by queuing a task in a `requestAnimationFrame()` callback.
requestAnimationFrame(() => {
setTimeout(() => {
const text = textBox.textContent;
updateWordCount(text);
checkSpelling(text);
saveChanges(text);
}, 0);
});
});
下圖呈現了延後非必要更新至下一個影格後的效果,可縮短處理時間,進而縮短整體互動延遲時間。
雖然在先前的程式碼範例中,在 requestAnimationFrame()
呼叫中使用 setTimeout()
的做法確實有點難懂,但這是一種有效的方法,可在所有瀏覽器中運作,確保非關鍵程式碼不會封鎖下一個影格。
避免版面配置輾轉
版面配置衝突 (有時稱為強制同步版面配置) 是一種轉譯效能問題,會在版面配置同步發生時發生。這種情況會在您在 JavaScript 中更新樣式,然後在同一個工作中讀取樣式時發生,而且 JavaScript 中有許多屬性可能會導致版面配置耗盡資源。
版面配置衝突是效能瓶頸,因為更新樣式後,系統會立即在 JavaScript 中要求這些樣式的值,導致瀏覽器必須同步執行版面配置作業,而這項作業原本可以等待事件回呼執行完畢後再以非同步方式執行。
盡量縮短呈現延遲時間
互動標記的呈現延遲是指從互動事件回呼完成執行,到瀏覽器能夠繪製下一個影格,顯示產生的視覺變更之間的時間。
盡量縮小 DOM 大小
如果網頁的 DOM 很小,轉譯作業通常會很快完成。不過,當 DOM 變得非常大時,算繪工作會隨著 DOM 大小增加而擴大。算繪工作與 DOM 大小之間的關係並非線性關係,但大型 DOM 的算繪工作量確實比小型 DOM 多。大型 DOM 有兩種情況會造成問題:
- 在初始網頁轉譯期間,大型 DOM 需要大量工作才能轉譯網頁的初始狀態。
- 在回應使用者互動時,大型 DOM 可能會導致轉譯更新的成本過高,進而增加瀏覽器呈現下一個影格所需的時間。
請注意,在某些情況下,大型 DOM 無法大幅縮減。雖然您可以採取一些方法來縮減 DOM 大小,例如扁平化 DOM或在使用者互動期間新增 DOM,以便維持初始 DOM 大小,但這些技巧可能只能達到一定程度。
使用 content-visibility
延遲轉譯畫面外元素
您可以使用 CSS content-visibility
屬性,在網頁載入期間和回應使用者互動時,限制算繪工作量,這相當於在元素接近可視區域時,以延後算繪的方式進行。雖然 content-visibility
需要一些練習才能有效使用,但如果結果是縮短算繪時間,進而改善網頁的 INP,就值得一試。
使用 JavaScript 算繪 HTML 時,請留意效能成本
只要有 HTML,就會有 HTML 剖析作業。瀏覽器剖析 HTML 並將其轉換為 DOM 後,就必須套用樣式、執行版面配置計算,並接著算繪該版面配置。這是不可避免的成本,但您如何轉譯 HTML 很重要。
當伺服器傳送 HTML 時,瀏覽器會以串流的形式接收。串流是指伺服器傳送的 HTML 回應會分成多個區塊傳送。瀏覽器會在串流內容抵達時逐步剖析串流內容的片段,然後逐漸轉譯,藉此最佳化串流內容的處理方式。這是一種效能最佳化做法,可讓瀏覽器在網頁載入期間自動定期產生隱含的效能,而且您不必付費。
雖然首次造訪任何網站時都會涉及一些 HTML,但常見的做法是先從最少的初始 HTML 開始,然後再使用 JavaScript 填入內容區域。使用者互動後,系統也會針對該內容區塊進行後續更新。這通常稱為單頁應用程式 (SPA) 模型。此模式的一個缺點是,在用戶端使用 JavaScript 算繪 HTML 時,您不僅要支付 JavaScript 處理作業的成本來建立 HTML,瀏覽器也必須先完成剖析 HTML 並算繪,才能「不」產生。
不過,請務必記住,即使網站不是 SPA,也可能會透過 JavaScript 將 HTML 算繪成互動結果。只要您不會在用戶端上算繪大量 HTML,這通常不會造成問題,因為這可能會延遲下一個影格的呈現。不過,請務必瞭解這種方法在瀏覽器中算繪 HTML 的效能影響,以及如果您透過 JavaScript 算繪大量 HTML,這會如何影響網站對使用者輸入內容的回應速度。
結論
改善網站的 INP 是一項疊代程序。修正互動速度緩慢的問題後,您很可能會發現其他互動速度緩慢的問題,尤其是如果您的網站提供大量互動功能,就更有可能發生這種情況。因此,您也需要對這些互動進行最佳化。
改善 INP 的關鍵在於持之以恆。您可以逐步改善網頁的回應速度,讓使用者滿意您提供的體驗。當您為使用者開發新功能時,也可能需要進行相同的程序,以便針對使用者進行互動最佳化。這項作業需要花費時間和心力,但絕對值得。
主頁橫幅圖片取自 Unsplash,由 David Pisnoy 拍攝,並根據 Unsplash 授權進行修改。