ページライフサイクル

ドラフトコミュニティグループレポート,

このバージョン:
https://wicg.github.io/page-lifecycle/
課題管理:
GitHub
編集者:
(Google)
以前の編集者:
(Google)
(Google)

概要

本ドキュメントは、ブラウザがウェブページのライフサイクルを管理する能力をサポートするAPIを定義します。

この文書のステータス

この仕様は Web Platform Incubator Community Group によって公開されました。 W3C標準でもW3C標準化トラック上のものでもありません。 W3C Community Contributor License Agreement (CLA) のもと、限定的なオプトアウトや他の条件が適用されることにご注意ください。 W3Cコミュニティおよびビジネスグループについて詳しくは、こちらをご覧ください。

1. はじめに

多数のWebアプリ(およびタブ)が動作していると、メモリ・CPU・バッテリー・ネットワークなどの重要なリソースがすぐに使い過ぎとなり、ユーザー体験が悪化します。アプリケーションのライフサイクルは、現代のOSがリソースを管理する主要な手法です。

プラットフォームがアプリケーションライフサイクルをサポートするには、以下が必要です:

この提案は、Webページのライフサイクルが何かを定義し、Webアプリケーションがユーザーエージェントによってよく行われる2つの重要なライフサイクルイベントに応答できる拡張を追加することを目指しています:

2. ページライフサイクル状態

この仕様はWebページのライフサイクルが何かを定義し、Webアプリケーションがユーザーエージェントによってよく行われる2つの重要なライフサイクルイベントに応答できる拡張を追加します:

この仕様では、上記をサポートするために2つの新しいライフサイクル状態を正式化します:

TODO(panicker): 図を挿入予定

3. API

ページライフサイクルには以下の追加が含まれます:

partial interface Document {
    attribute EventHandler onfreeze;
    attribute EventHandler onresume;
    readonly attribute boolean wasDiscarded;
};

onfreezeonresume 属性は、それぞれ freeze および resume イベントの イベントハンドラーIDL属性です。

wasDiscarded 属性のgetterは、この Documentdiscarded ブール値を返します。

注: これらのAPIは Document に追加されています。 Window ではなく、 Page Visibility APIとの一貫性のためです。これらのAPIは既存APIと組み合わせて使われることを想定しています。[PAGE-VISIBILITY]

注: 加えて clientId および discardedClientIdWindow に追加され、破棄後にページを再訪してリロードする際のビュー状態復元をサポートします。これらは本イベントに反応するコードで利用される見込みです。

3.1. 使用例

freezeとresumeのハンドリング例:

const prepareForFreeze = () => {
  // 開いているIndexedDB接続を閉じる。
  // Webロックを解放する。
  // タイマーやポーリングを停止する。
};

const reInitializeApp = () => {
  // IndexedDB接続を復元する。
  // 必要なWebロックを再取得する。
  // タイマーやポーリングを再開する。
};

document.addEventListener('freeze', prepareForFreeze);
document.addEventListener('resume', reInitializeApp);

破棄後にビュー状態を復元する例: ユーザーが同じアプリ・URLで複数タブを開いている場合、両方がバックグラウンドかつ破棄されたとき、アプリは2つのタブを区別して正しい状態を復元する必要があります。この目的でWindowのclientIdとlastClientIdが使えます。

// IndexedDBに状態を保存する際、self.clientIdの現在値をレコードにセットしておくことで
// getPersistedState()で後から取得可能(タブが破棄後リロードされた場合など)。
const persistState = async (state) => {
  const record = {...state, cliendId: self.clientId};

  // レコードをIndexedDBやSessionStorageに保存...
}

// 渡されたクライアントIDに基づき、IndexedDBから状態レコードを取得。
const getPersistedState = async (clientId) => {
  // IndexedDBでレコードを検索...
};

// タブが以前破棄されていれば、self.lastClientId経由でそのクライアントIDの状態を取得。
if (document.wasDiscarded) {
  getPersistedState(self.lastClientId);
}

4. 機能ポリシー

入れ子になった閲覧コンテキストの実行状態を閲覧コンテキストから制御することは、 ユーザー体験を制御するために望ましい。アプリケーションは、文書がレンダリングされている状態ではない場合、またはビューポートと交差しない場合に、すべての 実行が入れ子になった閲覧コンテキスト内で停止すること(現在再生中の動画、 音声を含む)を望む場合がある。すべての実行を停止すると、 CPU 使用率が改善される可能性がある。これらのニーズを満たすため、2 つの機能ポリシーを定義する:

"execution-while-not-rendered"ポリシーは、 タスクの実行に関して、 入れ子になった閲覧コンテキスト閲覧コンテキストコンテナーレンダリングされている状態ではない場合に、実行すべきかどうかを制御する。

"execution-while-out-of-viewport"ポリシーは、 タスクの実行に関して、 入れ子になった閲覧コンテキスト閲覧コンテキストコンテナービューポートと交差するかどうかを、 対象要素と ルートの交差を計算するに従って判定した結果、交差しない場合に、実行すべきかどうかを制御する。

§ 5.2 HTML 標準に対する変更は、文書(および その子孫)を凍結状態に置くことによって、これを実現する。これは 次の 条件が満たされた場合に行われる:

これらの条件が満たされていない場合、文書は非凍結状態になる。

<!-- iframe は読み込まれた直後に凍結される。 -->

<iframe allow="execution-while-not-rendered 'none'"
  src="subframe.html" style="display:none"></iframe>
文書の凍結状態を更新する手順を、Document document に対して実行するには、次を行う:
  1. document閲覧コンテキスト入れ子になった閲覧コンテキストでない場合は、返る。

  2. document準備状態が「complete」でない場合は、 返る。

  3. elementを、document閲覧コンテキスト閲覧コンテキストコンテナーとする。

  4. frozennessを false とする。

  5. auto resume mediaを false とする。

  6. documentが「使用を許可されているexecution-while-not-rendered 機能の使用を許可されていない場合は、次を行う:

    1. elementレンダリングされていない場合は、frozennessを true に設定する。

  7. そうでなく、documentが「使用を許可されているexecution-while-out-of-viewport 機能の使用を許可されていない場合は、次を行う:

    1. elementビューポートと交差するかどうかを、対象 要素とルートの交差を計算するに従って判定した結果、交差しない場合は、frozennessを true に設定し、auto resume mediaを true に設定する。

  8. frozennessdocument凍結状態と等しくない場合は、文書の凍結状態を変更する を、documentfrozenness、およびauto resume mediaを指定して実行する。

5. 処理モデル

5.1. ワークレット・ワーカーの挙動変更

単一の ワークレットエージェントrealmグローバルオブジェクト所有ドキュメント凍結状態の場合、進行停止となる必要があります。 単一の 専用ワーカーエージェントrealmグローバルオブジェクト所有ドキュメントが非nullかつ 凍結状態の場合も 進行停止となる必要があります。

DedicatedWorkerGlobalScope workerGlobalScope所有ドキュメント判定手順:
  1. workerGlobalScope所有セットが1つの Document document なら、document を返す。

  2. workerGlobalScope所有セットが1つの DedicatedWorkerGlobalScope parentWorkerGlobalScope なら、parentWorkerGlobalScope所有ドキュメント を返す。

  3. nullを返す。

注: DedicatedWorkerGlobalScope所有セットは常に1つだけ要素を持ちます。

5.2. HTML標準の修正

5.2.1. ドキュメントのアンロード履歴トラバーサル

ドキュメントが bfcache(back forward cache) へ出入りする際、凍結状態がtrue/falseに遷移します。

5.2.2. イベントループ: 定義

置き換え: タスクは、その document がnullまたは 完全にアクティブな場合、実行可能。

修正後: タスクは、その document がnullまたは 完全にアクティブかつ 未凍結の場合、実行可能。

5.2.3. イベントループ: 処理モデル

レンダリングの更新中、Step #11後に以下のステップを追加:

完全にアクティブDocument doc それぞれについて、ドキュメント凍結状態更新手順docで実行。

5.2.4. 閲覧コンテキストの破棄

閲覧コンテキストやドキュメントの「discard」概念を「destroy」にリネームします。これにより、ユーザー向け属性 wasDiscarded に「discarded」という用語を使えます。

5.2.5. ドキュメントの初期化

Step #3の前に以下を追加:

閲覧コンテキストが以前破棄状態だった場合、Documentdiscardedブール値をtrueにセット。

5.2.6. iframe loadイベントの手順

Step #5後に以下を追加:

child documentドキュメント凍結状態更新手順を実行。

5.2.7. HTMLMediaElement

HTMLMediaElementresume frozen flag(初期値false)を持ちます。

5.2.8. メッセージの送信

注記追加:

注記: Window凍結されているときにメッセージを投稿した場合、 投稿メッセージタスクソースにキューされたイベントは、Window非凍結になるまで実行されない。あまりに多くのイベントが キューされた場合、ユーザーエージェントが破棄 する可能性があるのは、Window閲覧コンテキストである(リソースが逼迫した状況で破棄を認める一般規定の一環として)。

5.3. Service Worker標準への修正

5.3.1. Client

partial interface Client {
    readonly attribute ClientLifecycleState lifecycleState;
};

enum ClientLifecycleState {
    "active",
    "frozen"
};

Client オブジェクトは ライフサイクル状態 を持ち、これは ClientLifecycleState 列挙値のいずれかです。

5.3.1.1. lifecycleState

lifecycleState のgetter手順は、thisライフサイクル状態を返します。

5.3.1.2. matchAll(options)

Step #4 の変数名を変更します。

  1. matchedClientData を新しい リストとする。

Step #2.5.1 の前に挿入

  1. lifecycleStateGet Client Lifecycle Stateclient を渡して実行した結果とする。

Step #5.3.1 でリストに lifecycleState を追加

  1. windowData を «[ "client" → client, "ancestorOriginsList" → 新しい リスト, "lifecycleState" → lifecycleState ]»とする。

Step #5.4 で matchedClientData に lifecycleState を追加

  1. «[ "client" → client, "lifecycleState" → lifecycleState ]» を matchedClientData に追加する。

Step #6.2 で windowData の lifecycleState を Create Window Clientアルゴリズムに渡す

  1. windowClientCreate Window Clientアルゴリズムに windowData["client"], windowData["frameType"], windowData["visibilityState"], windowData["focusState"], windowData["ancestorOriginsList"], windowData["lifecycleState"] を引数として渡して実行した結果とする。

Step #6.3 の調整

  1. clientDatamatchedClientData で反復:

    1. clientObjectCreate Clientアルゴリズムに clientData["client"], clientData["lifecycleState"] を引数として渡して実行した結果とする。

    2. clientObject を clientObjects に追加する。

5.3.1.3. openWindow(url)

Step #7.5 の前に挿入

  1. lifecycleStateGet Client Lifecycle Statethis の関連 service worker client を渡して実行した結果とする。

Step #7.8.2 の調整(lifecycleState を渡す)

  1. clientCreate Window ClientnewContextWindow オブジェクトの environment settings object, frameType, visibilityState, focusState, ancestorOriginsList, lifecycleState を引数として実行した結果とする。

5.3.2. アルゴリズム

5.3.2.1. クライアントのライフサイクル状態取得

次のアルゴリズムを追加:

入力

client : service worker client

出力

state : 文字列

  1. state"active" にする。

  2. もし clientglobal object所有ドキュメント凍結状態なら state"frozen" にする。

  3. state を返す。

5.3.2.2. Create Client

入力に lifecycleState(文字列)を追加

出力の Step #2 の後に次を追加

  1. clientObjectライフサイクル状態lifecycleState にセットする。

5.3.2.3. Create Window Client

入力に lifecycleState(文字列)を追加

出力の Step #5 の後に次を追加

  1. windowClientライフサイクル状態lifecycleState にセットする。

5.4. ページライフサイクル処理モデル

5.4.1. 凍結状態(FROZENNESS state)

ドキュメントは以下の 凍結状態(FROZENNESS) のいずれかになります:

UA は、特定の状況でトップレベル 文書の凍結状態を変更するアルゴリズムに true を指定して実行することを選択してもよい。 たとえば、トップレベル閲覧コンテキストがバックグラウンドにあるか非表示であり、猶予期間が経過した場合、 UA はトップレベル 文書の凍結状態を変更するアルゴリズムに true を指定して実行することで、リソースを節約し、(フォアグラウンドの)ユーザー 体験の品質を維持できる。 具体例:

UA は通常、ユーザーがその閲覧コンテキストを再訪したときに、トップレベル 文書の凍結状態を変更するアルゴリズムに false を指定して実行する。さらに、UA は、十分なリソースが利用可能な場合、 バックグラウンドで定期的にトップレベル 文書の凍結状態を変更するアルゴリズムに false を指定して実行することを選択してもよい。

5.4.2. ドキュメントの凍結状態変更

トップレベルドキュメントの凍結状態変更Document topLevelDoc、boolean frozenness状態frozenness)の手順:
  1. Assert: doc閲覧コンテキストトップレベル閲覧コンテキストである。

  2. ドキュメントの凍結状態変更topLevelDoc, frozenness, false で実行。

  3. descendants子孫閲覧コンテキストのリストdoc)とする。

  4. 閲覧コンテキスト bdescendants で反復:

    1. descendantDocumentアクティブドキュメントb)とする。

    2. ドキュメントの凍結状態変更descendantDocument, frozenness, false で実行。

ドキュメントの凍結状態変更Document doc, boolean frozenness状態frozenness, boolean auto resume frozen media)の手順:
  1. もし frozenness が true なら freeze stepsdocauto resume frozen media で実行。

  2. そうでなければ resume stepsdoc で実行。

freeze stepsDocument doc, boolean auto resume frozen media)の手順:
  1. doc凍結状態 を true にセットする。

  2. freezeイベントを doc で発火する。

  3. elementsメディア要素のうち shadow-including descendantsdoc をルートとし、shadow-including tree orderで並べたものとする。

  4. elementelements で反復:

    1. もし elementpaused が false なら:

      1. elementresume frozen flagauto resume frozen media にセットする。

      2. media pauseelement に実行。

    注: frozenness 状態の代入がイベント発火より先になる順序は意図的です。

resume stepsDocument doc)の手順:
  1. elementsメディア要素のうち shadow-including descendantsdoc をルートとし、shadow-including tree orderで並べたものとする。

    1. elementelements で反復:

      1. もし elementsresume frozen flag が true なら:

        1. elementsresume frozen flag を false にセット。

        2. media playelement に実行。

  2. resumeイベントを doc で発火する。

  3. doc凍結状態 を false にセットする。

    注: frozenness 状態の代入がイベント発火の後になる順序は意図的です。

5.4.3. 破棄(Discarding)

各Documentは discarded ブール値(初期値false)を持つ。

discard で閲覧コンテキストを破棄するには、閲覧コンテキストをdestroyし、その理由がdiscardingによるものであることを記録する(子孫も同様)。

注: discardは通常、システムメモリ等のリソース不足時に解放目的で行う。一方destroyはユーザーがページ離脱等で通常の後処理として行う。

閲覧コンテキスト ― バックグラウンドかつ、そのドキュメントが VisibilityState hidden の場合、リソース圧迫時(例:メモリ不足)には discarded され得る。具体例:

トップレベル閲覧コンテキスト(ブラウザのタブ)がリソース圧迫や予期せぬ事象(プロセスクラッシュ等)で 破棄された後、ユーザーが再度タブを訪れた場合、Documentdiscarded ブール値が § 5.2.5 ドキュメントの初期化により true となります。

6. 謝辞

この仕様の改善につながる技術的な助言と提案をいただいた Dave Tapuska、 Fadi Meawad、 Ojan Vafai、 Olli Pettay、 Philip Walton、 そして Todd Reifsteck に特別な感謝を捧げます。

適合性

文書規約

適合性要件は記述的な断言と RFC 2119 の用語の組み合わせで表現されています。 この文書の規範部分における「MUST」「MUST NOT」「REQUIRED」「SHALL」「SHALL NOT」「SHOULD」「SHOULD NOT」「RECOMMENDED」「MAY」「OPTIONAL」といったキーワードは RFC 2119 の定義に従って解釈されます。 ただし、可読性のため、これらの語はすべて大文字では記載されていません。

この仕様のすべての文章は、 明示的に非規範とされた節・例・注記を除き、規範的です。[RFC2119]

この仕様の例は「for example」という語で始めるか、規範テキストと区別して class="example" が付与されて示されます。 例:

これは情報例の一例です。

情報注記は「Note」で始まり、規範テキストと区別して class="note" が付与されて示されます。 例:

注: これは情報注記の例です。

適合アルゴリズム

アルゴリズムの一部として命令形で書かれた要件(例:「先頭の空白文字を除去する」や「falseを返してこれらの手順を中止する」)は、アルゴリズム導入部で使われているキーワード("must"、"should"、"may" など)の意味で解釈されます。

アルゴリズムや特定の手順として表現された適合要件は、最終的な結果が同等であれば、どのような方法で実装してもかまいません。 特に、この仕様で定義されたアルゴリズムは理解しやすいことを意図しており、パフォーマンスを重視したものではありません。 実装者は最適化を推奨します。

索引

本仕様で定義された用語

参照で定義される用語

参考文献

規範的参考文献

[CSS21]
Bert Bos; 他. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. URL: https://drafts.csswg.org/css2/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; 他. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[PERMISSIONS-POLICY-1]
Ian Clelland. Permissions Policy. URL: https://w3c.github.io/webappsec-permissions-policy/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997年3月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SERVICE-WORKERS-1]
Alex Russell; 他. Service Workers 1. URL: https://w3c.github.io/ServiceWorker/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

参考情報

[PAGE-VISIBILITY]
Jatinder Mann; Arvind Jain. Page Visibility (Second Edition). 2013年10月29日. REC. URL: https://www.w3.org/TR/page-visibility/

IDL索引

partial interface Document {
    attribute EventHandler onfreeze;
    attribute EventHandler onresume;
    readonly attribute boolean wasDiscarded;
};

partial interface Client {
    readonly attribute ClientLifecycleState lifecycleState;
};

enum ClientLifecycleState {
    "active",
    "frozen"
};