Chrome のメモリモードと省エネモードについてデベロッパーが知っておくべきこと

Chrome 108 では、メモリセーバー モードと省エネモードという 2 つの新しいモードが導入され、ユーザーは Chrome がシステム リソースをどのように利用するかをより細かく制御できるようになりました。

これらの新しいモードは主にユーザー向けですが、サイトのユーザー エクスペリエンスに影響を与える可能性があるため、ウェブ デベロッパー様が注意すべき影響がいくつかあります。

この記事では、これらの新しいモードがもたらす可能性のある影響と、ウェブ デベロッパーが可能な限り最適なエクスペリエンスを提供するためにできることについて説明します。

メモリセーバー モード

メモリセーバー モードが有効になっていると、バックグラウンドでしばらく使用されていないタブが事前に破棄されます。これにより、アクティブなタブや、実行中の他のアプリのメモリが解放されます。ユーザーは特定のサイトのタブを破棄しないよう Chrome に指示できますが、これはユーザーの設定によるものであり、デベロッパーが管理することはできません。

タブが破棄されると、そのタブのタイトルとファビコンはタブバーに引き続き表示されますが、ページ自体は、タブが通常どおり閉じられた場合とまったく同じように消えます。ユーザーがそのタブに戻ると、ページは自動的に再読み込みされます。

コンテンツのみのページでは、タブを破棄して再読み込みしてもユーザー エクスペリエンスに影響しない可能性がありますが、複雑なユーザーフローを持つリッチでインタラクティブなサイトでは、サイトがユーザーが中断したところからページを正確に復元できない場合、フロー途中でリロードすると非常に不便な場合があります。

タブを破棄してメモリを節約することは、Chrome が長年行ってきたことですが、これはシステムのメモリ不足が生じている場合にのみ行われていました。比較的まれな事象であるため、ウェブ デベロッパーは発生に気付いていなかった可能性があります。

Chrome 108 以降、タブの破棄はより一般的になるため、サイトがこれらの発生を適切に処理することが重要です。

タブの破棄を処理する際のベスト プラクティス

タブの破棄は、ウェブ デベロッパーにとって新しい課題ではありません。ユーザーは、タスクを完了する前に、意図的または誤ってページを再読み込みすることが常に可能でした。そのため、ユーザーが離れてから戻ってきた場合に復元できるように、サイトがユーザーの状態を保存することが常に重要でした。

最も重要な考慮事項は、ユーザーの状態を保存するかどうかではなく、いつ保存するかです。これは重要なポイントです。タブが破棄されたときにトリガーされるイベントがないため、タブが破棄されたという事実にデベロッパーが対応する方法がありません。デベロッパーは、この可能性を予測して事前に準備する必要があります。

ユーザーの状態を保存する最適なタイミングは次のとおりです。

  • 状態が変化するたびに定期的に。
  • タブがバックグラウンドに移行するたび(visibilitychange イベント)。

状態を保存するのに適さないタイミングは次のとおりです。

  • beforeunload イベント コールバック内。
  • unload イベント コールバック内。

これらのイベントは完全に信頼性が低く、タブが破棄される場合など、多くの状況で発生しないため、状態を保存するには最適なタイミングではありません。

ページが破棄されるときに発生するイベントについては、ページのライフサイクル イベントの図をご覧ください。この図からわかるように、タブはイベントが発生しなくても「非表示」状態から「破棄済み」状態に移行できます。

Page 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 アナリティクスでカスタム イベント パラメータを設定すると、タブの破棄によって発生したページビューの割合を測定できます。

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

アナリティクス プロバイダの場合は、このディメンションをデフォルトでプロダクトに追加することを検討してください。

メモリセーバー モードでサイトをテストする

ページを読み込んでから別のタブまたはウィンドウで chrome://discards にアクセスすることで、ページの破棄がどのように処理されるかをテストできます。

chrome://discards UI で、リストから破棄するタブを見つけて、[アクション] 列の [緊急破棄] をクリックします。

破棄タブへのリンクの場所を示す chrome://discards UI のスクリーンショット

これによりタブが破棄されるため、再度アクセスして、ページが閉じたときと同じ状態に再読み込みされたことを確認できます。

なお、現在のところ、webdriver や puppeteer などのテストツールでタブの破棄を自動化する方法はありません。ただし、タブの破棄と復元はページの再読み込みとほぼ同じであるため、ユーザーフローの途中で再読み込み後にユーザー状態が復元されることをテストすれば、破棄 / 復元でも機能する可能性があります。2 つの主な違いは、タブが破棄されたときに beforeunloadpagehideunload イベントがトリガーされないことです。そのため、これらのイベントに依存せずにユーザー状態を保持する場合は、再読み込みを使用して破棄 / 復元の動作をテストできます。

省エネモード

省エネモードを有効にすると、Chrome はディスプレイのリフレッシュ レートを下げてバッテリーを節約します。これにより、スクロールやアニメーションの忠実度、動画のフレームレートに影響します。

一般的に、省エネモードをサポートするための対応は不要です。このモードを有効にすると、アニメーション遷移requestAnimationFrame() の CSS と JavaScript の API は、ディスプレイの更新レートの変化に自動的に調整されます。

このモードが問題となる可能性がある主なシナリオは、サイトがすべてのユーザーに対して特定の更新レートを前提とする JavaScript ベースのアニメーションを使用している場合です。

たとえば、サイトが requestAnimationFrame() ループを使用していて、コールバック間で正確に 16.67 ミリ秒が経過すると想定している場合、省電力モードが有効になっていると、アニメーションの実行速度は 2 倍に遅くなります。

なお、デフォルトの更新レートが 60 Hz であることをすべてのユーザーに想定することは、現在の多くのデバイスでは当てはまらないため、常に問題となってきました

ディスプレイのリフレッシュ レートを測定する

ディスプレイのリフレッシュ レートを測定する専用の Web API はありません。また、一般に、現在の API でリフレッシュ レートを測定することは推奨されません

既存の API で最善の方法は、連続する requestAnimationFrame() コールバック間のタイムスタンプを比較することです。これは、ほとんどの場合、特定の時点でのリフレッシュ レートを近似するのに役立ちますが、リフレッシュ レートがいつ変更されたかを知ることはできません。そのためには、requestAnimationFrame() ポーリングを常に実行する必要がありますが、これはユーザーのエネルギーやバッテリー駆動時間を節約するという目標に反します。

省エネモードにおけるサイトのテスト

省エネモードでサイトをテストする方法の一つは、Chrome の設定でモードを有効し、デバイスの電源がオフのときに実行するように設定することです。

電源プラグを抜くことができるデバイスがない場合は、以下の手順に沿って手動でモードを有効にすることもできます。

  1. chrome://flags/#battery-saver-mode-available フラグを有効にします。
  2. chrome://discards にアクセスし、[バッテリー セーバー モードを切り替える] リンクをクリックします(重要: リンクを機能させるには、#battery-saver-mode-available フラグを有効にする必要があります)。

省エネモードを有効にするリンクの場所を示す chrome://discards UI のスクリーンショット

有効にすると、サイトを操作して、アニメーションや遷移が適切な速度で実行されるなど、すべてが想定どおりに表示されることを検証できます。

概要

Chrome のメモリセーバー モードと省エネモードは主にユーザー向けの機能ですが、適切に処理しないと、サイトへのアクセスに悪影響を及ぼす可能性があるため、デベロッパーにとっては影響があります。

一般に、これらの新しいモードは、既存の開発者のベスト プラクティスを念頭に置いて設計されています。デベロッパーが長年の実績のあるウェブのベスト プラクティスに従っている場合、サイトはこれらの新しいモードでも引き続き正常に動作します。

ただし、この投稿で紹介した手法のいずれかがサイトに含まれている場合、この 2 つのモードを有効にすると問題が増える可能性があります。

優れたエクスペリエンスを提供していることを確認する最善の方法は、ユーザーの環境と同じ条件でサイトをテストすることです。