瞭解如何最佳化網站與下一個顯示畫面的互動方式。
Interaction to Next Paint (INP) 是穩定的 Core Web Vitals 指標,可評估網頁回應使用者互動的整體效能,方法是觀察使用者造訪網頁期間,網頁對所有符合資格的互動的延遲時間。最終 INP 值是觀察到的最長互動 (有時忽略離群值)。
為了提供良好的使用者體驗,網站應力求與下一個顯示畫面互動 (互動時間不超過 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,這些工作包括剖析指令碼以確保其語法有效、將其編譯為 bytecode,然後執行。
視指令碼大小而定,這項工作可能會在主執行緒上引入長時間的工作,導致瀏覽器延遲回應其他使用者互動。為了讓網頁在載入期間能回應使用者輸入內容,請務必瞭解如何減少在載入期間執行長時間任務的可能性,讓網頁保持快速回應。
最佳化事件回呼
輸入延遲時間只是 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 授權進行修改。