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 イベントがトリガーされないことです。そのため、これらのイベントに依存せずにユーザー状態を保持する場合は、再読み込みを使用して破棄/復元の動作をテストできます。

省エネモード

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

通常、デベロッパーは省エネモードをサポートするために何もする必要はありません。このモードを有効にすると、アニメーション遷移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 つのモードを有効にすると、ユーザーの問題が増加する可能性があります。

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