1. はじめに
このセクションは規定ではありません。
ウェブブラウザの主な目的は、HTML、CSS、画像リソースをユーザーのために画面上のピクセルへ変換することです。ウェブページのパフォーマンス測定は、多くの場合、これらの作業(テキストや画像などのコンテンツを画面に描画する)の所要時間を計測することに関係します。こうしたタイミングの使い方には、ページのパフォーマンスやロード時のユーザー体験を評価する様々な方法がありますが、根本的にはどれも時間を測定する共通の手段から始まります。
これはペイントタイミングを一般的な仕組みとして測定する方法を定める基礎的なドキュメントです。この基盤を用いて、First Paint(最初のペイント)およびFirst Contentful Paint(最初の内容ペイント)の指標を定義します。ペイント測定の他の具体的な事例については、他の文書で定められる場合があります。
具体的に、本仕様では以下を扱います:
-
画像がデコードされペイント準備が整う時刻の測定
-
要素が描画される時刻の測定
-
描画された要素のサイズの測定
-
描画された要素が目に見えるコンテンツを含むかどうかの判定
1.1. 最初のペイントおよび最初の内容ペイント
ロードは単一の瞬間ではなく、単一の指標で完全に捉えられるものではありません。ロード体験には、ユーザーが「速い」と感じるか「遅い」と感じるかに影響する複数の瞬間があります。
First Paint(FP)はその重要な瞬間の最初であり、続いてFirst Contentful Paint(FCP)が続きます。これらの指標は、ブラウザが指定されたドキュメントを描画するタイミングを示します。これはユーザーにとって「何かが起きているか?」という疑問に答える重要な瞬間です。
両指標の主な違いは、FPがブラウザがそのドキュメントで何かを初めて描画した時点を示すのに対し、FCPはDOMから最初の画像またはテキストコンテンツが描画された時点を示すことです。
1.2. 使用例
const observer= new PerformanceObserver( function ( list) { const perfEntries= list. getEntries(); for ( const perfEntryof perfEntries) { // エントリーの処理 // 分析や監視のための報告 // ... } }); // ペイントタイミング通知のためのオブザーバ登録 observer. observe({ entryTypes: [ "paint" ]});
2. 用語
ペイント:ユーザーエージェントが「ペイント」(または「レンダー」)を実行したとは、レンダーツリーを画面上のピクセルに変換したことを指します。正式には、ユーザーエージェントがイベントループのレンダリングの更新ステップを実行したときに「レンダー」されたとみなします。
注意: レンダリング処理は非常に複雑であり、タイムスタンプはユーザーエージェントがこのパイプラインで記録できる最新のタイムスタンプ(ベストエフォート)であるべきです。通常、このAPIではフレームがOSへ表示のため送信される時刻が推奨されます。
生成コンテンツ疑似要素は、以下すべてを満たす場合ペイント可能疑似要素です:
-
疑似要素の 算出済み visibility は
visibleです。 -
疑似要素は非空のボックスを生成します。
CSS画像 imgは、以下すべてを満たす場合内容画像です:
DOMString
は、非空であるとは、文書の空白文字以外の文字を1文字以上含む場合です。
要素 targetは、次のいずれかを満たす場合内容有りです:
-
targetがテキストノードを子に持ち、非空テキストを表し、そのノードのused opacityが0より大きい。
注意: これは組版疑似要素がテキストノードのopacityを上書きする場合をカバーします。
-
targetがbackground-imageとして内容画像を持ち、used background-sizeの幅と高さが0でない値である。
-
targetが
canvasで、context modeがnone以外に設定されている。 -
targetが描画された子孫を持つsvg要素である。
-
targetが起点要素で、ペイント可能疑似要素を表し、それが内容画像または非空テキストを表す。
要素は、以下のいずれかの場合タイミング対象です:
ペイント可能境界矩形を要素targetで計算するには、次の手順を実行します:
-
boundingRectを
getBoundingClientRect()をtargetで実行した結果とする。 -
boundingRectを返す。
注意: overflowやoverflowなボックスに含まれる要素は、ペイント可能境界矩形がクリップされません。どちらの場合でも、要素はスクロール操作で可視化できるためです。
要素 elは、次の全てを満たす場合ペイント可能です:
-
el は レンダリング中である。
-
el の 算出済み visibility は
visibleである。 -
el および全ての先祖の 算出済み opacity が0より大きい。
注:
paintableな 要素 がユーザーに見えないケースも存在します。例えば、テキストと背景色が同じ場合などです。 このような要素も first contentful paint を計算する際には paintable とみなされます。 -
el の paintable bounding rect が スクロール領域と document のいずれかで交差している。
注: これは要素がゼロサイズにスケーリングされた場合や、
display、または: nonedisplayで内容が空の矩形になる場合を含みます。: contents注: 一般的なルールとして、要素がビューポート内、またはスクロールやズームによってビューポートに表示される可能性がある場合は paintable です。
First paint エントリは、
DOMHighResTimeStamp
を含み、これはユーザーエージェントがナビゲーション後に初めてレンダリングされた時刻を報告します。デフォルトの背景の塗りは除外しますが、非デフォルトの背景やiframeの囲われたボックスは含みます。これはページのロードで開発者が最初に重要視する瞬間、すなわちユーザーエージェントがページを描画し始めたときです。
ブラウジングコンテキスト ctxは、以下のいずれかを満たす場合ペイントタイミング対象です:
-
ctxが最上位ブラウジングコンテキストである。
-
ctxが入れ子ブラウジングコンテキストで、ユーザーエージェントがctxにペイントタイミング報告を設定している。
注意: これにより、ユーザーエージェントはメインフレーム以外の一部フレームに対してのみペイントタイミングを有効化できます。例えば、ユーザーエージェントがメインフレームの情報を漏らす可能性がある場合、クロスオリジンiframeに対してペイントタイミングを無効化することもできます。
3. ペイントタイミングミキシン
このセクションは規範的ではありません。
PaintTimingMixin
インターフェースは、レンダリングサイクルに関連するタイムスタンプを公開します。
これは、PerformanceEntry
を拡張したプラットフォームオブジェクトに含まれます。具体的には、PerformanceElementTiming、
LargestContentfulPaint、
PerformanceEventTiming、
PerformancePaintTiming、
およびPerformanceLongAnimationFrameTimingによって拡張されます。
paintTime
属性は、レンダリングの更新ループの終了時点のタイムスタンプを表し、
presentationTime
は、フレームがユーザーに提示される際にマークされる実装固有のタイムスタンプを表します。
HTML標準でレンダリングの更新から呼び出されるペイントタイミングのマークアルゴリズムが両方の属性を設定します。
塗りタイミングに依存するエントリの属性、たとえば LargestContentfulPaint
の
renderTime
(および startTime)は、
通常、各個別のタイムスタンプではなくデフォルト塗りタイムスタンプを返すため、
presentationTime
の実装依存な性質に左右されません。
3.1. PaintTimingMixin
インターフェース
[Exposed =Window ]interface mixin {PaintTimingMixin readonly attribute DOMHighResTimeStamp ;paintTime readonly attribute DOMHighResTimeStamp ?; };presentationTime
PaintTimingMixin
インターフェースミキシンを含むオブジェクトには、関連付けられたペイントタイミング情報(nullまたはペイントタイミング情報)があります。
ペイントタイミング情報は、 構造体です。以下の項目を持ちます:
- レンダリング更新終了時刻
- 実装依存のプレゼンテーション時刻
-
Null または
DOMHighResTimeStamp
paintTime
属性のゲッターステップは、this
の ペイントタイミング情報 の レンダリング更新終了時間 を返します。
presentationTime
属性のゲッターステップは、存在する場合、this の ペイントタイミング情報 の 実装依存の提示時間 を返します。
ペイントタイミング情報 paintTimingInfo のデフォルトペイントタイムスタンプを取得するには、 paintTimingInfo の 実装依存の提示時間 が null でない場合はそれを返し、それ以外の場合は paintTimingInfo の レンダリング更新終了時間 を返します。
4. PerformancePaintTiming
インターフェイス
[Exposed =Window ]interface :PerformancePaintTiming PerformanceEntry { [Default ]object (); };toJSON PerformancePaintTiming includes PaintTimingMixin ;
PerformancePaintTiming
は PerformanceEntry
インターフェイスの下記属性を拡張します:
-
name属性のgetterは、最小限のフレーム属性付けのためにDOMStringを返さなければならない。name の値として考えられるものは次の通り:-
: first paint 用"first-paint" -
: first contentful paint 用"first-contentful-paint"
-
-
entryType属性のgetterはを返さなければならない。"paint" -
startTime属性のgetterは、塗りが発生した時刻のDOMHighResTimeStampを返さなければならない。 -
duration属性のgetterは 0 を返さなければならない。 -
toJSON が呼び出されたときは、 default toJSON steps を
PerformancePaintTiming用に実行する。
NOTE: PerformancePaintTiming
を実装するユーザーエージェントは、 を supportedEntryTypes
に含める必要があります。
グローバルオブジェクト の ブラウジングコンテキスト が paint-timing eligible である場合です。
これにより、開発者は特定の ブラウジングコンテキスト に対してペイントタイミングのサポートを検出できます。
5. 処理モデル
5.1. 関連付けられた画像リクエスト
各 Element
には 関連付けられた画像リクエスト があり、これは 画像リクエスト または null で、初期値は null です。
Element
型の element の処理モデルが
HTMLImageElement,
SVGImageElement,
または HTMLVideoElement
が新しい画像リソース(例:画像やポスター画像として表示されるため)を作成するとき、
element の 関連付けられた画像リクエスト は作成された画像リソースの 画像リクエスト に設定されます。
Note: URLの
scheme が "data" である画像リソースは、取得されませんが依然として読み込む必要がある 画像リクエスト
を持ちます。このリクエストは Element
の 関連付けられた画像リクエスト となり得ます。
Note: 現在の記述は具体的な アルゴリズムには言及していないため曖昧です。該当する処理モデルがより統一された処理モデルを持つ場合、より厳密に記述できます。
全ての Element
は 関連付けられた背景画像リクエスト
のリストを持ち、初期値は空の配列です。Element
element のスタイルが新しい画像リソース(背景画像として表示されるため)を必要とする場合、新しいリソースによって作成された 画像リクエスト が element の 関連付けられた背景画像リクエスト に追加されます。
NOTE: Element
は複数の 画像リクエスト を持つことができます。例えば、
background-image プロパティが複数値を持つ場合です。下記例では、一つの background-image プロパティが4つの
画像リクエスト を生成し、それぞれが下記アルゴリズムで記録・報告されます。
<!DOCTYPE html> < style > div { background-image : url( https://images.example/background1.png ), url( https://images.example/background2.png ); } </ style > < div ></ div > < div ></ div >
5.2. ペイントタイミングの記録
pending image record は、以下の 構造体の 要素を持つものです。
-
element、
Element -
request、画像リクエスト
-
loadTime,
DOMHighResTimeStamp
Element
は所有テキストノード集合(初期値は空の順序付き集合で、Text
ノードを含む)を持ちます。
Document
は過去に報告されたペイント集合(初期値は空の順序付き集合で、文字列を含む)を持ちます。
Document
はレンダリング待ち画像(初期値は空のリストで、保留画像レコードを含む)を持ちます。
Document
は描画済みテキストを持つ要素集合(初期値は空の順序付き集合で、Elementを含む)を持ちます。
5.2.1. CSS仕様への修正
画像リクエストがElementelementの関連背景画像リクエスト内で完全に利用可能となった場合、elementおよび画像リクエストを入力として読み込み完了画像の処理アルゴリズムを実行します。
5.2.2. HTML仕様への修正
Element
elementの関連画像リクエストが完全に利用可能となった場合、elementとその関連画像リクエストを入力として読み込み完了画像の処理アルゴリズムを実行します。
Text
ノードtextを初めてペイントしたとき、次の手順を実行してください:
-
textがフォントフェイスのフォントブロック期間のためにペイントされない場合は、戻る。
-
追加としてtextをelementの所有テキストノード集合に加える。
5.2.3. 読み込み完了画像の処理
Element
elementと画像リクエスト imageRequestを入力として実行するには:
-
rootをelementのルートとする。
-
rootが
Documentでなければ、戻る。 -
nowをelementの現在の高精度時刻(elementの関連グローバルオブジェクトに基づく)とする。
-
recordを保留画像レコード(element element、request imageRequest、loadTime now)とする。
-
recordをrootのレンダリング待ち画像に追加する。
5.3. ペイントタイミングの報告
5.3.1. 最初の内容ペイント
-
もし document の これまでに報告されたペイントの集合 が
を含む場合、false を返す。"first-contentful-paint" -
もし document が 要素を1つ以上保持しており、そのどれかが paintable かつ contentful であれば、true を返す。
-
それ以外の場合、false を返す。
5.3.2. ペイントタイミングのマーク
-
document の ブラウジングコンテキスト が ペイントタイミング対応でない場合、return する。
-
paintTimingInfo を新しい paint timing info とし、その レンダリング更新終了時刻 は document の 関連グローバルオブジェクトでの current high resolution time の値とする。
-
paintedImages を新しい 順序付き集合 とする。
-
paintedTextNodes を新しい 順序付き集合 とする。
-
doc の images pending rendering リストの各 record について:
-
record の request が available かつペイント可能な場合、次を行う:
-
record を paintedImages に追加する。
-
record を doc の images pending rendering リストから削除する。
-
-
-
Elementelement を doc の 子孫それぞれについて:-
もし element が doc の set of elements with rendered text に含まれていれば続行。
-
element の set of owned text nodes が空であれば続行。
-
set-append で element を doc の set of elements with rendered text に追加する。
-
set-append で element を paintedTextNodes に追加する。
-
-
reportedPaints を document の これまでに報告されたペイントの集合とする。
-
frameTimingInfo を document の current frame timing infoとする。
-
document の current frame timing info を null に設定する。
-
flushPaintTimings を次の手順とする:
-
もし reportedPaints に
が含まれず、かつユーザーエージェントが first paint をマークする設定になっていれば、report paint timing を document・"first-paint" ・paintTimingInfo で呼び出す。"first-paint" 注: first paint はデフォルトの背景の塗りを除外しますが、非デフォルトの背景の塗りは含みます。
-
もし document が first contentful paint を報告すべき であれば:
-
report paint timing を document・
・ paintTimingInfo で呼び出す。"first-contentful-paint"
注: 親フレームは子iframeのペイントイベントを認識せず、逆も同様です。つまりiframeのみを含むフレームでは(iframeの外枠ボックスにより)first paint は起きても、first contentful paint は起きません。
注: document は
や"first-paint" を必ずマークするとは限りません。完全に空白な document は first paint をマークしないことがあり、 非contentful要素のみを含むドキュメントも first contentful paint をマークしないことがある。"first-contentful-paint" 注: first paint のマークは任意です。paint timing を実装するユーザーエージェントは最低でも first contentful paint をマークすべきです。
-
-
report largest contentful paint を document・paintTimingInfo・ paintedImages・paintedTextNodes で呼び出す。
-
report element timing を document・paintTimingInfo・ paintedImages・paintedTextNodes で呼び出す。
-
もし frameTimingInfo が null でない場合、queue a long animation frame entry を document・frameTimingInfo・paintTimingInfo で呼び出す。
-
-
ユーザーエージェントが実装依存の presentation time をサポートしない場合は flushPaintTimings を呼び出して return する。
-
次の手順を並列で実行:
-
現在のフレームがユーザーにpresentationされたタイミングで実装依存の適切な時刻まで待つ。
-
paintTimingInfo の 実装依存のプレゼンテーション時刻 を document の 関連グローバルオブジェクトでの current high resolution time で設定する。
-
document の cross-origin isolated capability が false の場合:
-
paintTimingInfo の 実装依存のプレゼンテーション時刻 を4ミリ秒の倍数またはそれ以上粗視化した値にする。
-
current high resolution time の値が paintTimingInfo の 実装依存のプレゼンテーション時刻 になるまで待つ。
-
-
グローバルタスクをキューし、performance timeline task source にて document の 関連グローバルオブジェクト で flushPaintTimings を実行する。
-
5.3.3. ペイントタイミングの報告
-
新しい
PerformancePaintTimingオブジェクトnewEntryをdocumentの関連レルムで作成し、以下の属性を設定する:-
newEntryの
name属性にpaintTypeを設定。 -
newEntryの
entryType属性にを設定。"paint" -
newEntryの
startTime属性にデフォルトペイントタイムスタンプ(paintTimingInfoで取得)を設定。 -
newEntryの
duration属性に0を設定。
-
-
newEntryのペイントタイミング情報にpaintTimingInfoを設定。
-
追加としてpaintTypeをdocumentの過去に報告されたペイント集合に加える。
5.4. 共通アルゴリズム
5.4.1. ペイントタイミング向け公開
要素elementがペイントタイミングのために露出されているかどうか判定するには、Documentまたはnullであるdocumentを使い、次の手順を実行する:
-
elementが接続済みでなければ、falseを返す。
-
documentがnullの場合、documentをelementの関連設定オブジェクトの関連グローバルオブジェクトの関連付けられたdocumentとする。
-
documentが完全にアクティブでなければ、falseを返す。
-
elementのルートがdocumentと一致しなければ、falseを返す。
-
trueを返す。
6. 謝辞
この仕様の技術的な貢献・提案を通じて改善に導いてくださった全てのコントリビューターに特別な感謝を表します。