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 で、破棄するタブをリストから見つけて、[Actions] 列の [Urgent Discard] をクリックします。

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

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

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

省エネモード

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

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

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

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

なお、すべてのユーザーに対してデフォルトのリフレッシュ レートを 60 Hz に設定することは、現行の多くのデバイスではそうならないため、デベロッパーが常に問題視してきました。

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

ディスプレイのリフレッシュ レートを測定するための専用のウェブ API はなく、一般に、現在の API を使用して測定することはおすすめしません

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

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

省エネモードでサイトをテストする方法の 1 つは、Chrome の設定でこのモードを有効にして、デバイスが電源に接続されていないときに実行されるように設定することです。

取り外せるデバイスがない場合は、次の手順でモードを手動で有効にすることもできます。

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

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

この機能を有効にすると、サイトを操作して、すべてが想定どおりに表示されること(アニメーションや遷移が希望する速度で実行されるなど)を確認できます。

概要

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

一般に、これらの新しいモードは既存のデベロッパーのベスト プラクティスを念頭に置いて設計されています。デベロッパーが長年にわたりウェブのベスト プラクティスを実施していれば、これらの新しいモードでもサイトが問題なく動作するはずです。

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

いつものように、ユーザー エクスペリエンスが優れていることを確認する最善の方法は、ユーザーの条件と一致する条件でサイトをテストすることです。