瞭解何謂輸入延遲,並瞭解減少輸入延遲時間的技巧,藉此加快互動速度。
與網路上的互動相當複雜,無論使用者發生哪種活動,都會在瀏覽器中進行。然而,這些測試的共通之處在於,它們會在事件回呼開始執行之前產生一些輸入延遲。本指南將說明什麼是輸入延遲,以及如何縮短輸入延遲時間,加快網站互動的執行速度。
什麼是輸入延遲?
「輸入延遲時間」是指從使用者初次與網頁互動 (例如輕觸畫面、使用滑鼠或按下按鍵) 開始算起,直到互動事件回呼開始執行為止。每次互動都從一些輸入延遲開始。
![簡化輸入延遲的圖表。左側是滑鼠遊標後方有星星圖案的線條藝術,代表互動的開始。右側是輪盤的線條藝術,表示互動的事件處理常式開始執行的時間。中間的空格會以大括號表示的輸入延遲時間。](https://web.dev/static/articles/optimize-input-delay/image/a-simplified-visualizatio-d1514b424d9ec.png?authuser=7&hl=zh-tw)
部分輸入延遲時間不可避免:作業系統一律需要一些時間來辨識輸入事件,並將其傳送至瀏覽器。不過,這部分的輸入延遲時間通常不明顯,而且網頁本身可能會發生其他狀況,可能導致輸入延遲夠長,進而造成問題。
如何考量輸入延遲
一般來說,您應該盡量縮短互動的各個環節,才能讓網站達到「與下一個顯示內容的互動」(INP) 指標「良好」的成效。門檻,無論使用者的裝置為何。讓檢查的輸入延遲時間只是達到該門檻的一環。
因此,建議您以最短的輸入延遲時間達到 INP 的「良好」門檻。但請注意,不太可能完全消除輸入延遲。只要您能在使用者嘗試與網頁互動時,避免造成主執行緒過多的工作,輸入延遲時間應該就會夠低,以免發生問題。
如何盡可能縮短輸入延遲時間
如前文所述,我們無法避免某些輸入延遲,但另一方面,「可以」避免某些輸入延遲。如有輸入延遲過長的問題,請考慮下列幾點。
避免重複執行會導致主執行緒工作過度的計時器重複執行
JavaScript 中有兩個常用的計時器函式,有可能是產生輸入延遲的原因:setTimeout
和 setInterval
。兩者的差異在於,setTimeout
會安排在指定時間之後執行回呼。另一方面,setInterval
會安排每 n 毫秒執行一次回呼,直到以 clearInterval
停止計時器為止。
setTimeout
本身並沒有問題,事實上,這有助於避免長時間工作。不過,這取決於逾時發生的「時間」,以及使用者是否在逾時回呼執行時嘗試與網頁互動。
此外,setTimeout
可以在迴圈中或以遞迴方式執行,在其運作方式更為類似 setInterval
,但在上一個疊代作業完成之前,建議不要安排下一個疊代作業。雖然這意味著,每次呼叫 setTimeout
時,迴圈都會產生到主執行緒,但您應謹慎確保回呼不會執行過多工作。
setInterval
會以間隔執行回呼,因此更有可能與互動的方式互動。這是因為與 setTimeout
呼叫的單一例項不同,後者屬於一次性回呼,且「可能」涉及使用者互動。setInterval
定期特性使其「可能」會透過互動方式產生,因此會增加互動的輸入延遲時間。
![Chrome 開發人員工具效能分析器的螢幕截圖,顯示輸入延遲。計時器函式觸發的工作,會在使用者啟動點擊互動之前發生。不過,計時器會延長輸入延遲時間,導致互動的事件回呼比其他事件晚執行。](https://web.dev/static/articles/optimize-input-delay/image/a-screenshot-the-perform-0955d1c357d1f.png?authuser=7&hl=zh-tw)
setInterval
呼叫所註冊的計時器,造成輸入延遲,如 Chrome 開發人員工具的效能面板中顯示。附加的輸入延遲會導致互動的事件回呼比其他可能早執行。
如果計時器是在第一方程式碼中觸發,您就可以自行控管。請評估自己是否有用,或盡可能減少其中的工作。不過,第三方指令碼中的計時器會不一樣。您通常無法控制第三方指令碼的功能,而修正第三方程式碼的效能問題時,通常需要與利害關係人合作,判斷是否需要使用特定的第三方指令碼。如果有的話,請與對方聯絡,向第三方指令碼供應商確認可以採取哪些行動來修正網站的效能問題。
避免長時間執行的工作
減少輸入延遲時間過長的方法之一,就是避免長時間工作。如果主執行緒在互動期間有過多作業造成主執行緒遭到阻斷,那麼這類工作會增加這些執行緒的輸入延遲時間,以免長時間工作完成。
![視覺化工作延長輸入延遲時間的時間。頂層而言,互動會在單一長時間工作執行後不久發生互動,導致輸入延遲嚴重導致事件回呼比預期晚得多。在底層中,互動發生的時間大致相同,但是系統會產生,並將長時間的工作分成幾個較小的工作,讓互動的事件回呼更快執行。](https://web.dev/static/articles/optimize-input-delay/image/a-visualization-how-long-af65d3963b8fb.png?authuser=7&hl=zh-tw)
除了盡可能減少在任務中執行的工作量之外,並一律盡量在主執行緒上盡可能減少工作,您可以拆分長時間的工作,改善使用者輸入內容的回應速度。
留意重疊的互動情形
如有互動相同,部分 INP 最佳化作業尤其棘手。互動重疊表示在您與某個元素互動後,您在初次互動可能顯示下一個頁框之前,再次與網頁互動。
![說明工作何時可重疊,以導致輸入延遲。在此情況下,點擊互動會與 keydown 互動重疊,增加 keydown 互動的輸入延遲時間。](https://web.dev/static/articles/optimize-input-delay/image/a-depiction-when-tasks-8c6449133de24.png?authuser=7&hl=zh-tw)
造成互動重疊的原因可能就和使用者在短時間內進行許多互動一樣簡單。當使用者在表單欄位輸入文字,短時間內可能會發生許多鍵盤互動,就可能發生這種情況。如果處理重要事件的工作成本特別高 (例如會在後端發出網路要求時,自動完成欄位常見欄位),您有下列幾種做法:
- 考慮取消彈跳輸入內容,以限制事件回呼在特定時間範圍內的執行次數。
- 使用
AbortController
取消傳出的fetch
要求,以免主執行緒在處理fetch
回呼時擁塞。注意:AbortController
執行個體的signal
屬性也可用來取消事件。
另一項造成輸入延遲時間增加的原因,是重疊互動造成的成本很高。特別是 JavaScript 中的動畫可能會觸發多個 requestAnimationFrame
呼叫,而這些呼叫可能會以使用者互動的方式呈現。如要解決這個問題,請盡可能使用 CSS 動畫,以免將可能耗用大量資源的動畫影格排入佇列,但如果要這麼做,請務必避免使用非合成動畫,讓動畫主要在 GPU 和合成器執行緒上執行,而非在主執行緒上執行。
結論
雖然輸入延遲不見得是互動執行過程的大部分時間,但請務必瞭解,每次互動都會花上不少時間,在您可減少的情況下減少。如果您觀察到長時間輸入的延遲情況,則有機會減少延遲時間。請避免使用週期性計時器回呼、切斷長時間工作,以及瞭解潛在的互動重疊,這有助於縮短輸入延遲時間,進而加快網站使用者的互動速度。
主頁橫幅來自 Erik Mclean 的 Unsplash 網站上。