介紹scheduler.yield():Chrome用於優化INP的最新API
已發表: 2023-09-15毫無疑問,2023 年 Google 的重點是響應能力。
到目前為止,他們:
- 將交互從實驗狀態移至待定狀態;
- 宣布 INP 將在 2024 年 3 月取代首次輸入延遲,成為新的核心 Web 響應能力指標;
- 開始在 Search Console 中標記 INP 問題,並向未達到良好響應閾值的網站發送電子郵件。
現在,Chrome 團隊宣布他們正在對新的調度程序 API – Scheduler.yield()進行原始試驗。
Scheduler.yield()預計將幫助開發人員提高網站的響應能力,為他們提供一種更簡單、更好的方法來將控制權交還給主線程。
請繼續閱讀,了解有關新 API 以及如何在您的網站上試用的更多信息。
快速回顧長任務和主線程
如果您很清楚任務和主線程是什麼,請隨意跳過這一部分。 如果沒有,我們鼓勵您閱讀這篇快速回顧,因為它是理解Scheduler.yield()以及如何實現它的基礎。
瀏覽器作為工作所做的一切都被視為任務。 這包括渲染、解析 HTML 和 CSS、運行您編寫的 JavaScript 代碼以及您可能無法直接控制的其他事情。
主線程是瀏覽器完成大部分工作的地方。
不幸的是,主線程一次只能處理一個任務。 如果一個任務運行時間超過 50 毫秒,則被認為是一個長任務。
遇到長任務意味著瀏覽器將根據需要運行它來完成它。 完成後,控制權將交還給主線程,允許瀏覽器處理隊列中的下一個任務。
長任務是頁面響應能力差的主要原因,因為它們延遲了瀏覽器響應用戶輸入的能力。 此外,JavaScript 及其運行到完成模型是阻塞主線程的罪魁禍首。
這就是為什麼它被認為是渲染阻塞資源——當瀏覽器遇到它時,它必須在執行其他操作之前下載、解析和執行它。
好消息是,僅僅因為您的代碼在瀏覽器中啟動任務並不意味著您必須等到該任務完成才能將控制權返回到主線程。
您可以通過在任務中顯式讓出來分解長任務。
簡而言之,任務讓出可確保瀏覽器不會過於專注於一項任務,從而錯過或延遲響應其他重要任務或用戶交互。
不幸的是,當前的收益策略並不完美......
為什麼使用scheduler.yield():當前產量策略的問題
屈服於主線程並不是一個新概念。 相當長一段時間以來,開發人員一直在使用不同的收益策略來分解長任務:
1.setTimeout()
setTimeout() 允許您安排任務在指定的延遲後或定期運行。 即使您指定超時為 0,這也會將回調的執行推遲到單獨的任務中。當您有多個函數需要一個接一個地運行時,此方法非常有效。
缺點:精度無法保證。 由於隊列中的其他任務,回調可能不會在指定的延遲之後準確運行。 此外,如果您正在循環中處理大量數據集,則該任務可能會變得非常耗時,尤其是在處理數百萬個條目時。
2. 請求空閒回調()
requestIdleCallback() 允許您安排任務在瀏覽器可能有的任何空閒期間運行。 它對於執行非緊急任務而不影響用戶體驗非常有用。
缺點: requestIdleCallback()以盡可能低的優先級調度任務,這意味著如果主線程擁塞,調度的任務可能永遠無法運行。
3.isInputPending()
isInputPending() 可以隨時執行以檢查用戶是否正在嘗試與頁面上的元素交互。 如果是,該函數返回true ; 如果不是,則返回false 。
想像一下,您有一系列任務要執行,但不想中斷用戶交互。 您可以使用isInputPending()和yieldToMain()函數來確保用戶輸入在與頁面交互時不會延遲。
缺點: isInputPending()可能並不總是在用戶輸入後立即返回 true。 這是因為操作系統需要時間來告訴瀏覽器交互發生了。 這意味著其他代碼可能已經開始執行。
這些是返回主線程的一些流行方法。 如您所見,每種方法都有其自身的缺點。
但最顯著的缺點是:
當您通過推遲代碼在後續任務中運行來屈服於主線程時,該代碼將被添加到任務隊列的最末尾。
為什麼這是一個問題?
這是一個三重答案:
- 增加邏輯錯誤的機會:由於延遲代碼被放置在任務隊列的末尾,因此瀏覽器在返回延遲任務之前可能會執行其他任務。 這可能會影響函數的執行順序,並可能導致邏輯錯誤或意外行為。
- 執行延遲:如果隊列中有很多任務,則瀏覽器可能需要花費大量時間才能到達並執行延遲的代碼。
- 不可預測性:很難準確預測延遲任務何時運行,因為它取決於隊列中已有任務的數量和性質。 這種不可預測性可能會給調試和性能優化帶來挑戰。
總之,雖然使用當前的策略屈服於主線程可以幫助維護響應式用戶界面,但它也會在確保代碼及時有序執行方面帶來挑戰。
介紹scheduler.yield()
Chrome 運行 Scheduler.yield() 的原始試驗令人興奮,因為它是一個調度程序 API,可以解決其他生成策略的所有缺點。
最重要的是,它是一個解決方案,使開發人員和所有者能夠實現響應式網站和良好的 INP 分數,同時無縫執行其餘代碼。
那麼關於Scheduler.yield()的炒作到底是什麼呢?
對於初學者來說, scheduler.yield()是一個專用的yield 函數。 例如,setTimeout() 用於分解長任務並讓出主線程,但它更多的是函數副作用而不是默認選項。
其次, scheduler.yield()將剩餘的工作發送到隊列的前面。 這意味著您想要在屈服後立即恢復的工作不會讓位於其他來源的任務。
簡單地說:
Scheduler.yield()為您提供了兩全其美的功能 – 您可以通過屈服來提高站點的響應能力和 INP 分數,並確保您在屈服後想要完成的工作不會被延遲。
如何嘗試新的調度程序 API
從 Chrome 115 開始,您可以自行測試 Scheduler.yield。
要試驗新的 API,只需按照 Google 的說明操作即可:
- 如果您想在本地試驗 Scheduler.yield,請在 Chrome 的地址欄中輸入chrome://flags ,然後從“實驗性 Web 平台功能”部分的下拉列表中選擇“啟用”。 這將使 Scheduler.yield (以及任何其他實驗性功能)僅在您的 Chrome 實例中可用。
- 如果您想在可公開訪問的源上為真正的 Chromium 用戶啟用 Scheduler.yield,則需要註冊 Scheduler.yield 源試用版。 這使您可以在給定的時間內安全地試驗建議的功能,並為 Chrome 團隊提供有關如何在現場使用這些功能的寶貴見解。 有關原產地試驗如何運作的更多信息,請閱讀本指南。
測試後,您還可以提供有關如何改進它的反饋。
安全測試!
NitroPack 如何幫助解鎖主線程
將長任務分解為更小的塊對於為用戶提供快捷的體驗至關重要。
但如果您能夠先發製人地優化一些繁重的 JavaScript,不是更好嗎?
這就是 NitroPack 的用武之地。
憑藉其35 多項高級 Web 性能功能,NitroPack 幫助全球 180,000 多個網站實現卓越的用戶體驗、核心 Web 生命力和轉化率。
NitroPack 最顯著的優勢之一是它處理 JavaScript 執行的方式。
安裝 NitroPack 後,我們的服務會延遲非關鍵資源的加載,直到檢測到用戶交互。
此外,得益於我們專有的資源加載機制,NitroPack 可以重新安排將資源提供給主線程的方式。 我們這樣做是為了通過從主線程卸載任務來利用現代 CPU 的多核特性。
這樣,我們可以保證您的主線程保持暢通並可用於處理用戶交互。