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

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

雖然這些新模式主要面向使用者,但確實有一些影響值得網頁開發人員留意,因為這些模式可能會影響網站的使用者體驗。

這篇文章將說明這些新模式的潛在影響,以及網路開發人員可採取哪些措施,確保提供最佳體驗。

記憶體節省模式

啟用記憶體節省模式後,Chrome 會主動捨棄背景中閒置一段時間的分頁。這樣就能釋出記憶體,供使用中的分頁和可能正在執行的其他應用程式使用。使用者可以指示 Chrome 不要捨棄特定網站的分頁;不過,這是使用者偏好設定,開發人員無法控制。

當分頁遭到捨棄時,其標題和 favicon 仍會顯示在分頁列中,但頁面本身會消失,就像分頁已正常關閉一樣。如果使用者再次造訪該分頁,系統會自動重新載入該分頁。

如果是純內容網頁,捨棄和重新載入分頁可能不會影響使用者體驗,但如果是含有複雜使用者流程的互動式網站,如果網站無法將網頁還原至使用者離開時的狀態,在流程中途重新載入網頁可能會讓使用者感到非常不便。

為節省記憶體,Chrome 多年以來一直會捨棄分頁,但只有在系統記憶體不足的情況下才會這麼做。由於這種情況相對罕見,網頁開發人員可能不知道自己會遇到這種情況。

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

處理分頁捨棄的最佳做法

捨棄分頁並不是網頁程式開發人員新的挑戰。使用者在完成工作前,隨時都可能會重新載入網頁,不論是故意或意外。因此,網站儲存使用者狀態一向十分重要,這樣在使用者離開網站後再回來時,網站就能還原使用者狀態。

最重要的考量因素並非「是否」儲存使用者狀態,而是「何時」儲存。這一點非常重要,因為在捨棄分頁時,系統不會觸發任何事件,因此開發人員無法對捨棄分頁的情況做出反應。開發人員必須預先考量這項可能性,並做好準備。

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

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

儲存狀態最糟糕的時機如下:

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

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

您可以參考網頁生命週期事件圖表,瞭解在網頁遭到捨棄時,系統會觸發哪些事件。如圖表所示,分頁能夠從「隱藏」狀態轉換為「捨棄」狀態,而沒有任何事件觸發。

網頁生命週期 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 UI 中,找出清單中要捨棄的分頁,然後按一下「動作」欄中的「緊急捨棄」

chrome://discards 使用者介面的螢幕截圖,顯示連結至棄置分頁的位置

這會捨棄分頁,讓您重新查看分頁,並驗證重新載入的頁面是否與您離開時的狀態相同。

請注意,目前無法透過 webdriver 或 puppeteer 等測試工具自動捨棄分頁;不過,由於分頁捨棄和還原的運作方式與重新載入網頁幾乎相同,因此如果您在使用者流程中途重新載入網頁後,測試使用者狀態是否已還原,那麼在捨棄/還原作業中也可能會成功。兩者的主要差異在於,當分頁遭到捨棄時,beforeunloadpagehideunload 事件不會觸發,因此只要您不依賴這些事件保留使用者狀態,就可以使用重新載入功能來測試捨棄/還原行為。

省電模式

啟用省電模式後,Chrome 會降低螢幕的重新整理頻率,以節省電池電力,這會影響捲動和動畫的真實度,以及視訊影格速率。

一般來說,開發人員無須採取任何行動即可支援節能模式。啟用此模式後,適用於動畫轉場效果requestAnimationFrame() 的 CSS 和 JavaScript API 會自動調整顯示器更新率的任何變更。

這個模式可能會發生問題的主要情況,是當網站使用以 JavaScript 為基礎的動畫,並假設所有使用者都有特定的刷新率。

舉例來說,如果您的網站使用 requestAnimationFrame() 迴圈,並假設在回呼之間會經過 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 使用者介面的螢幕截圖,顯示啟用省電模式的連結位置

啟用後,您可以與網站互動,確認所有內容是否正常顯示,例如動畫和轉場效果是否以預期速度執行。

摘要

雖然 Chrome 的記憶體節省模式和節能模式主要面向使用者,但如果處理不當,可能會對造訪網站的使用者體驗造成負面影響,因此對開發人員而言仍有影響。

一般來說,這些新模式的設計理念是參考現有的開發人員最佳做法。如果開發人員持續遵循長期的網站最佳做法,建議讓網站持續使用這些新模式。

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

如往常,要確認您提供的體驗是否優質,最好的方法就是以與使用者相符的條件測試網站。