Chrome' 記憶體和節能模式的開發人員須知

Chrome 108 推出兩種全新模式:「記憶體節省模式」和「節能模式」,方便使用者進一步控管 Chrome 使用其系統資源的方式。

雖然這些新模式主要是以使用者為主,但網站開發人員也必須留意這些規定,因為這可能會影響使用者的瀏覽體驗。

本文將介紹這些新模式的潛在影響,以及網頁開發人員可以採取哪些措施來確保提供最佳體驗。

記憶體節省模式

記憶體節省模式啟用後,Chrome 會主動捨棄一段時間在背景未使用的分頁。這會釋出使用中的分頁以及其他執行中應用程式的記憶體。使用者可以指示 Chrome 不要捨棄特定網站的分頁;不過,這是使用者偏好設定,不是開發人員可以控管的項目。

捨棄分頁時,分頁標題和網站小圖示仍會顯示在分頁列,但頁面本身會消失,原來分頁為正常關閉狀態。如果使用者再次造訪該分頁,系統會自動重新載入該分頁。

如果是純內容網頁,捨棄並重新載入分頁可能不會影響使用者體驗,但如果網站提供豐富的互動式網站,且使用者流程十分複雜,那麼在網站流程中間重新載入,如果無法將網頁還原至使用者離開的確切位置,就會對其造成極大不便。

為了節省記憶體空間,Chrome 多年來一直致力於研發分頁功能,但只有在系統處於記憶體壓力的情況下,這項機制才算完成。由於這種情況相對罕見,網頁開發人員可能不知道自己會遇到這種情況。

從 Chrome 108 版開始,分頁捨棄功能會變得更加普遍,因此網站必須能夠妥善處理這類情況。

處理分頁捨棄作業的最佳做法

捨棄分頁並不是網頁程式開發人員新的挑戰。使用者可能刻意或不小心在完成任務前重新載入網頁。因此,網站儲存使用者狀態始終重要,以便在使用者離開和返回時還原狀態。

最重要的考量並非「是否」儲存使用者狀態,而是儲存「何時」。這點非常重要,因為沒有任何事件會在分頁捨棄時觸發,因此開發人員無法針對正在發生的情況做出回應。相反地,開發人員必須預期這種可能性,並事先做好準備。

儲存使用者狀態的最佳時機如下:

  • 定期變更狀態。
  • 每當分頁在背景執行時 (visibilitychange 事件)。

儲存狀態最差的時間為:

  • beforeunload 事件回呼中。
  • unload 事件回呼中。

這些是儲存狀態的最糟時機,因為這些事件完全不可靠,而且在許多情況下不會觸發 (包括捨棄分頁時)。

您可以參閱網頁生命週期事件圖表,瞭解頁面被捨棄時,應觸發哪些事件。如圖表所示,分頁可從「隱藏」狀態變更為「捨棄」狀態,而且不會觸發任何事件

頁面 Lifecycle API 狀態和事件流程。以視覺化方式呈現本文件所說明的狀態和事件流程。

事實上,只要網頁處於「隱藏」狀態狀態,我們無法保證任何其他事件會在瀏覽器捨棄或遭使用者終止前觸發,因此請務必將所有未儲存的使用者狀態一律儲存在 visibilitychange 事件中,因為可能無法收到其他機會。

以下程式碼概述了一些範例邏輯,只要目前使用者狀態發生變更,或使用者將分頁進入背景或離開分頁時,這些邏輯就會立即排入佇列:

let state = {};
let hasUnstoredState = false;

function storeState() {
  if (hasUnstoredState) {
    // Store `state` to localStorage or IndexedDB...
  }
  hasUnstoredState = false;
}

export function updateState(newState) {
  state = newState;
  hasUnstoredState = true;
  requestIdleCallback(storeState);
}

document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    storeState();
  }
});

偵測已捨棄分頁

如前文所述,雖然無法偵測到即將捨棄的分頁,但可能會偵測到使用者返回分頁並重新載入頁面之後,就捨棄了分頁。在這些情況下,document.wasDiscarded 屬性會是 true。

if (document.wasDiscarded) {
  // The page was reloaded after a discard.
} else {
  // The page was not reloaded after a discard.
}

如要瞭解使用者遇到這類情境的頻率,建議您設定分析工具擷取這項資訊。

舉例來說,您可以在 Google Analytics 中設定自訂事件參數,找出捨棄分頁帶來的瀏覽量百分比:

gtag('config', 'G-XXXXXXXXXX', {
  was_discarded: document.wasDiscarded,
});

如果你是分析服務供應商,建議將這項維度預設新增至產品。

在記憶體節省模式下測試網站

你可以載入網頁,然後在另一個分頁或視窗中前往 chrome://discards,測試網頁處理代碼的捨棄情形。

chrome://discards 使用者介面中,從清單中找出要捨棄的分頁,然後按一下「動作」欄中的「緊急捨棄」

chrome://discards UI 的螢幕截圖,顯示用於捨棄分頁的連結位置

這麼做會捨棄分頁,方便你再次造訪,確認網頁重新載入後的狀態與離開時的狀態相同。

請注意,目前無法利用 Webdriver 或 Puppeteer 等測試工具自動捨棄分頁。不過,由於分頁捨棄和還原作業與頁面重新載入幾乎相同,因此如果您在使用者流程中途中重新載入後,使用者狀態就已復原,則或許也能捨棄/還原。兩者的主要差異在於,捨棄分頁時不會觸發 beforeunloadpagehideunload 事件,因此只要您不依賴這些事件來保留使用者狀態,即可使用重新載入功能測試捨棄/還原行為。

節能模式

啟用節能模式後,Chrome 會降低螢幕刷新率,進而影響捲動和動畫擬真度和視訊畫面更新率,藉此節省電池電力。

一般來說,開發人員無須採取任何行動即可支援節能模式。啟用動畫轉換requestAnimationFrame() 的 CSS 和 JavaScript API,會在啟用這個模式後,自動調整螢幕刷新率的變化。

之所以發生這個模式,主要原因是網站使用的 JavaScript 動畫會假設所有使用者達到特定刷新率。

舉例來說,如果你的網站使用 requestAnimationFrame() 迴圈,且假設每次回呼間會經過正好 16.67 毫秒,則在啟用節能模式的情況下,動畫的執行速度將是 16.67 毫秒。

請注意,對所有使用者假設預設的刷新率是 60 Hz,因此開發人員一直以來都很有問題,因為許多現有裝置都需要如此。

評估螢幕刷新率

目前沒有專門的網頁 API 可用於評估螢幕刷新率,而且一般來說不建議嘗試透過目前的 API 這麼做。

開發人員可以利用現有 API 的最佳做法,是比較連續的 requestAnimationFrame() 回呼之間的時間戳記。雖然這種做法在大部分的情況下都能估算出特定時間點的刷新率,但無法在重新整理頻率變更時通知您。有鑑於此,您仍須持續執行 requestAnimationFrame() 輪詢,這無法達到節約耗電量或電池續航力的目標。

在節能模式中測試網站

如要在省電模式下測試網站,其中一種方法是在 Chrome 的設定中啟用該模式,並將模式設為在裝置未接上電源時執行。

如果您的裝置無法拔除電源,也可以按照下列步驟手動啟用此模式:

  1. 啟用 chrome://flags/#battery-saver-mode-available 旗標。
  2. 前往 chrome://discards,然後點選「切換省電模式」連結 (重要事項:您需要啟用 #battery-saver-mode-available 旗標,這個連結才能正常運作)。

chrome://discards UI 螢幕截圖,顯示啟用節能模式的連結位置

啟用這項功能後,您可以與網站互動,確認一切外觀都符合預期,例如動畫和轉場效果會以所需的速度播放。

摘要

Chrome 的記憶體節省模式和節能模式主要是提供給使用者的功能,但若未妥善處理,可能會對開發人員造成負面影響。

一般來說,這些全新模式設計時,我們考量了開發人員目前採用的最佳做法。如果開發人員持續遵循長期的網站最佳做法,建議讓網站持續使用這些新模式。

不過,如果您的網站包含本文提及的任一做法,那麼只有在啟用這兩種模式時,使用者才會發生問題。

一如往常,為了確保您能提供良好的體驗,最好的方法就是使用符合使用者訪客的條件來測試網站。