レンダリング パフォーマンス

サイトやアプリがうまく動作しないと、ユーザーはすぐに気づきます。そのため、レンダリング パフォーマンスの最適化は非常に重要です。

今日のウェブユーザーは、アクセスするページがインタラクティブでスムーズであることを期待しています。そのため、デベロッパーは、この点に時間と労力を注ぐ必要があります。ページは、読み込みが速いだけでなく、ライフサイクル全体を通じてユーザーの入力にすばやく応答する必要があります。実際、ユーザー エクスペリエンスのこの側面は、Interaction to Next Paint(INP)指標で測定されるものです。INP が良好であるということは、ページがユーザーのニーズに一貫して確実に応答していることを意味します。

ページがすばやく反応していると感じさせる主な要素は、ユーザー操作に応じて実行する JavaScript の量ですが、ユーザーが期待しているのはユーザー インターフェースの視覚的な変化です。ユーザー インターフェースの視覚的な変更は、いくつかの種類の作業の結果であり、多くの場合、レンダリングと総称されます。この作業は、ユーザー エクスペリエンスが高速で信頼できるものになるように、できるだけ早く行う必要があります。

ユーザー操作にすばやく応答するページを作成するには、HTML、JavaScript、CSS がブラウザでどのように処理されるかを理解し、作成したコード(および組み込んだサードパーティ コード)が可能な限り効率的に実行されるようにする必要があります。

デバイスのリフレッシュ レートに関する注意事項

スマートフォンでウェブサイトを操作しているユーザー。
ディスプレイのリフレッシュ レートは、ユーザー入力に反応するウェブサイトを構築する際に重要な考慮事項です。

現在、ほとんどのデバイスは画面を 1 秒間に 60 回更新します。更新のたびに、画面に表示されるビジュアル出力が生成されます。これは一般にフレームと呼ばれます。次の動画では、フレームのコンセプトについて説明しています。

Chrome DevTools の [Performance] パネルに表示されるフレーム。カーソルが上部のフィルムストリップをスクラブすると、モバイル ナビゲーション メニューが「開く」状態にアニメーション化されるときに、各フレームの拡大表示がツールチップ内に表示されます。

デバイスの画面は常に一定のレートで更新されますが、デバイスで実行されるアプリは、必ずしもそのリフレッシュ レートに一致する十分なフレームを生成できるとは限りません。たとえば、アニメーションや遷移が実行されている場合、ブラウザはデバイスのリフレッシュ レートに合わせて、画面が更新されるたびに 1 つのフレームを生成する必要があります。

一般的なディスプレイのリフレッシュ レートは 1 秒間に 60 回であるため、簡単な計算から、ブラウザが各フレームを生成するのに 16.66 ミリ秒かかることがわかります。しかし実際には、ブラウザにはフレームごとに独自のオーバーヘッドがあるため、すべての作業を 10 ミリ秒以内に完了する必要があります。このバジェットを満たせないと、フレームレートが低下し、ページ コンテンツが画面上でジャダーします。この現象は、一般にジャンクと呼ばれます。

ただし、目標は、行おうとしている作業の種類によって異なります。10 ミリ秒のしきい値を満たすことは、アニメーションにとって重要です。アニメーションでは、画面上のオブジェクトが 2 つのポイント間の一連のフレームにわたって補間されます。ユーザー インターフェースの不連続な変化(つまり、間にモーションを挟まずに、ある状態から別の状態に移行すること)については、ユーザーが瞬時に感じる時間枠で変化を実現することをおすすめします。このような場合、100 ミリ秒がよく引用される数値ですが、INP 指標の「良好」のしきい値は 200 ミリ秒以下であり、さまざまな機能を備えた幅広いデバイスに対応できます。

アニメーションに必要な多くのフレームを生成してジャンクを回避すること、またはユーザー インターフェースの個別の視覚的な変化をできるだけ早く生成することなど、目標が何であれ、ブラウザのピクセル パイプラインの仕組みを理解することは、作業に不可欠です。

ピクセル パイプライン

ウェブ デベロッパーとして、知っておくべき、また注意すべき 5 つの主要な領域があります。これらの 5 つの領域は、最も制御しやすい領域であり、それぞれがピクセルから画面へのパイプラインの重要なポイントを表しています。

JavaScript、スタイル、レイアウト、ペイント、コンポジットの 5 つのステップを含む完全なピクセル パイプライン。
ピクセル パイプライン全体の図。
  • JavaScript: JavaScript は通常、ユーザー インターフェースの視覚的な変更を伴う処理に使用されます。たとえば、jQuery の animate 関数、データセットの並べ替え、ページへの DOM 要素の追加などです。ただし、視覚的な変化をトリガーするために JavaScript が厳密に必要というわけではありません。CSS アニメーション、CSS トランジション、Web Animations API を使用して、ページ コンテンツをアニメーション化できます。
  • スタイル計算: 一致するセレクタに基づいて、どの CSS ルールがどの HTML 要素に適用されるかを判断するプロセスです。たとえば、.headline は、headline のクラスを含む class 属性値を持つ HTML 要素に適用される CSS セレクタの例です。そこから、ルールが判明すると、ルールが適用され、各要素の最終的なスタイルが計算されます。
  • レイアウト: 要素に適用されるルールがわかると、ブラウザはページのジオメトリ(要素が占めるスペースの量や、画面上の表示位置など)の計算を開始できます。ウェブのレイアウト モデルでは、1 つの要素が他の要素に影響を与える可能性があります。たとえば、<body> 要素の幅は通常、ツリーの上下にある子要素のサイズに影響するため、ブラウザにとってこのプロセスは非常に複雑になる可能性があります。
  • ペイント: ペイントは、ピクセルを塗りつぶすプロセスです。これには、ページ上の要素のレイアウトが計算された後に、テキスト、色、画像、枠線、影、そして基本的に要素のすべての視覚的な側面を描画することが含まれます。描画は通常、レイヤと呼ばれる複数のサーフェスに対して行われます。
  • 合成: ページの一部が複数のレイヤに描画されている可能性があるため、ページが想定どおりにレンダリングされるように、正しい順序で画面に適用する必要があります。これは、要素が別の要素と重なる場合に特に重要です。誤りがあると、ある要素が別の要素の上に誤って表示される可能性があります。

ピクセル パイプラインの各部分は、アニメーションにジャンクを導入したり、ユーザー インターフェースの個別の視覚的な変更であってもフレームの描画を遅らせたりする可能性があります。したがって、コードがトリガーするパイプラインの部分を正確に把握し、レンダリングに必要なピクセル パイプラインの部分のみに変更を制限できるかどうかを調査することが重要です。

「ペイント」に関連して「ラスタライズ」という用語を聞いたことがあるかもしれません。これは、ペイントが実際には次の 2 つのタスクであるためです。

  1. 描画呼び出しのリストを作成する。
  2. ピクセルを埋めています。

後者は「ラスタライズ」と呼ばれます。そのため、DevTools でペイント レコードが表示される場合は、ラスタライズが含まれていると考える必要があります。一部のアーキテクチャでは、描画呼び出しのリストの作成とラスタライズが異なるスレッドで行われますが、これはデベロッパーが制御できるものではありません。

すべてのフレームでパイプラインのすべての部分に触れるとは限りません。実際、JavaScript、CSS、Web Animations API のいずれかを使用して視覚的な変更を行う場合、特定のフレームに対してパイプラインが通常実行される方法は 3 つあります。

1. JS / CSS > スタイル > レイアウト > ペイント > コンポジット

完全なピクセル パイプライン。省略されたステップはありません。

「レイアウト」プロパティ(幅、高さ、位置など、要素のジオメトリを変更するプロパティ。left や top CSS プロパティなど)を変更すると、ブラウザは他のすべての要素をチェックして、ページを「リフロー」する必要があります。影響を受けた領域は再塗装する必要があり、最終的な塗装要素を合成して元に戻す必要があります。

2. JS / CSS > スタイル > ペイント > コンポジット

レイアウト ステップを省略したピクセル パイプライン。

CSS で要素の「ペイントのみ」のプロパティ(background-image、color、box-shadow などのプロパティ)を変更した場合、ページに視覚的な更新を commit するためにレイアウト ステップは必要ありません。可能な限りレイアウト ステップを省略することで、次のフレームの生成に大きなレイテンシをもたらす可能性のある、コストのかかるレイアウト作業を回避できます。

3. JS / CSS > スタイル > コンポジット

レイアウトとペイントのステップが省略されたピクセル パイプライン。

レイアウトもペイントも必要としないプロパティを変更した場合、ブラウザは合成ステップに直接ジャンプできます。これは、アニメーションやスクロールなど、ページのライフサイクルで負荷の高いポイントをピクセル パイプラインで処理する最も安価で望ましい方法です。豆知識: Chromium は、可能な限りコンポジタ スレッドのみでスクロールが発生するようにページのスクロールを最適化します。つまり、ページが応答していない場合でも、ページをスクロールして、以前に画面に描画された部分を表示できます。

ウェブ パフォーマンスとは、作業を回避し、必要な作業の効率を可能な限り高める技術です。多くの場合、ブラウザに逆らうのではなく、ブラウザと連携することが重要です。パイプラインに以前に表示された作業は、計算コストの点で異なることに注意してください。一部のタスクは、本質的に他のタスクよりもコストが高くなります。

パイプラインのさまざまな部分について詳しく見ていきましょう。一般的な問題と、その診断方法および修正方法について説明します。

ブラウザのレンダリングの最適化

Udacity コースのスクリーンショット

ユーザーにとってパフォーマンスは重要です。優れたユーザー エクスペリエンスを構築するには、ウェブ デベロッパーは、ユーザー操作にすばやく反応し、スムーズにレンダリングするウェブサイトを構築する必要があります。パフォーマンス エキスパートの Paul Lewis が、ジャンクを排除し、60 フレーム/秒のパフォーマンスを維持するウェブアプリを作成する方法を説明します。このコースを修了すると、アプリのプロファイリングを行い、レンダリング パフォーマンスが最適でない原因を特定するために必要なツールを習得できます。また、ブラウザのレンダリング パイプラインを調べ、ユーザーが快適に使用できる高速なウェブサイトを簡単に構築できるパターンを見つけます。

これは Udacity が提供する無料のコースで、いつでも受講できます。