目次
はじめに
こんにちは、Webエンジニアの柴田です。
社内でパフォーマンス基礎の勉強会を行いました。
そこで、最新のパフォーマンス指標を含めたWebフロントエンド パフォーマンス基礎をまとめてみました。
なお、社内での勉強会および本記事をまとめるにあたって、久保田光則著 (2017)「Webフロントエンド ハイパフォーマンス チューニング」技術評論社と、web.devやMDNを大いに参考にさせていただいております。
Webパフォーマンスとは
パーフォマンスの定義は以下のように定義されてます。
「ユーザーの様々な振る舞いに対してウェブページが応答する速さ」
ブラウザレンダリングの仕組み
ブラウザは通常いくつかのコンポーネントによって構成されています。
チューニングをするために知っておきたい2つの重要なコンポーネントがあります
- レンダリングエンジン
ブラウザ内部で利用されるHTMLの描画エンジンを指します。
ブラウザそのものではなく、Webページのレンダリングのみを担当するソフトウェアコンポーネントです。
HTMLや画像ファイル、CSSファイル、Javascriptなどの各種リソースを読み取って、それらを画面上にピクセルとして描画します。レンダリングエンジンは描画のみを担当しているため、戻るボタンや進むボタン、更新ボタンといった普段利用しているWebブラウザのユーザーインターフェースは含まれていません。
- JavaScriptエンジン
JavaScriptの実行環境を提供するソフトウェアコンポーネントです。
ブラウザの拡張機能を実行することにも使用されてます。
JavaScriptエンジンの一つであるV8は、Node.jsでも利用されてます。
各ブラウザのレンダリングエンジンとJavaScript エンジンのまとめ
ブラウザ名 | レンダリングエンジン | JavaScript エンジン |
Chrome | Blink | V8 |
Microsoft Edge | Blink | V8 |
FireFox | Gecko | SpiderMonkey |
Safari | Webkit | Nitro |
IE | Trident | Chakra |
異なるブラウザで挙動が違う現象が起きるのはレンダリングエンジンまたはJavaScript エンジンが違うことが要因だったりします。
ブラウザレンダリングの流れ
ブラウザのアドレスバーにURLを入力し、Webページが表示されるまでにいくつかの処理工程があります。
工程を大きく分けて4つの処理に分類できます。
Loading
↓
Scripting
↓
Rendering
↓
Painting
上記4つの処理をまとめて、フレームと呼びます。
フレームの処理をさらに詳細に分類すると以下のようになります。
Loading リソースの読み込み
まず第一に行うのがリソース読み込みになります。
このフェーズでは、HTMLやCSS、Javascriptファイル、JPEG・WebPな どのリソースをダウンロードし、解析(パース)を行います。 ダウンロードされたHTMLとCSSはそれぞれDOMツリーやCSSOMツリーに変換されます。
Scripting Javascriptの読み込み
タイトル通り、Javascriptの実行を担当します。
Rendering レイアウトツリーの構築
Javascriptの実行が終わるとレイアウトツリーの構築が行われます。
Renderingのフェーズではスタイル計算とレイアウトの二つの処理が行われます。
・Calculate Style スタイル計算
DOMツリー内のDOM要素に対してどのCSSプロパティが当たるかを判断します。判断方法は全てのDOM要素に対して、CSSOMツリー内を全て参照して、CSSルールのCSSセレクタマッチング処理を総当たりで行います。
・Layout
Calculate StyleフェーズでDOM要素に対してどのようなCSSプロパティが当たるのかを計算し終えると、レンダリングエンジンはDOMツリー内の全てのノードの視覚的レイアウトの計算を行います。
レイアウト情報は下記のような情報を指します。
・要素の大きさ
・要素のマージ
・要素のパディング
・要素の位置
・要素のz軸の位置
Painting レンダリング結果の描画
DOMツリーのレイアウト情報の算出が終わると、最後のレンダリングの描画に移行します。このフェーズにてユーザーがやっと視認できる実際のピクセルを描画します。このフェーズには、Paint, Rasterize、Composite Layersの3つの処理を行います。
・Paint
内部の低レベルな2Dグラフィックスエンジン向けの命令を生成します。RenderTreeを元にDisplay Listと呼ばれる内部の低レベルグラフィックスのための命令列を生成します。
・Rasterize
生成された命名を用いて実際にピクセルへと描画します。このとき、レイヤーという単位で一枚一枚描画されます。レイヤーはz軸の上下関係を持ちます。複数のレイヤーが一枚の絵に合成される時に、z軸の上下関係を考慮して合成されます。
レイヤーが生成されるのは要素が以下の条件に当てはまる場合です。
・position: absolute; が適用されている
・position: fixed; が適用されている
・translate: translate3d(0 0 0)などの、GPUで描画合成されるCSSプロパティを持っている
・opacity プロパティが適用されていて、透過して背後のコンテンツが描画される必要がある
レイヤー単位でピクセルを作成する理由は再レンダリングが発生した時に、変更のないレイヤーを再利用するためです。
・Composite Layers
ピクセルにしたレイヤーを合成して最終的なレンダリング結果を生成します。
再レンダリング
再レンダリングとは、読み込みと描画が終わり、ユーザーやブラウザが何らかのアクションやJavascriptのコードの実行などによって、レンダリングが再度引き起こされることを指します。
再レンダリングの流れ↓
パフォーマンスの指標
RAIL
Google社の開発者である Ilya Grigorik 氏が提唱したパフォーマンスモデルです。RAILはResponse、Animation、Idle、Loadの各単語の頭文字をとって名付けられました。
https://web.dev/i18n/ja/rail/
・Response 50ミリ秒
ユーザーが何らかのアクションに対してWebページがUI上の変化を引き起こし、応答するまでの時間を指します。
ユーザーの入力によって開始された処理を100ミリ秒以内に完了することが推奨されています。目に見える応答を100ミリ秒以内に確保するために、50ミリ秒以内にユーザー入力イベントを処理することを推奨しています。
ユーザー入力イベントはボタンのクリック、フォームコントロールの切り替え、アニメーションの開始などほとんどの入力が対象となります。タッチドラッグやスクロールは対象外となります。
もしユーザー入力イベントが50ミリ秒以上かかる場合は、ローディングアイコンを画面に表示し、ユーザーに処理中の旨を示すように求められます。
・Animation フレームを10ミリ秒で生成
Animationはアニメーション中に連続して行われるフレームの中で1フレームの処理の時間の目安を指します。アニメーションの各フレームを10ミリ秒以内に生成することを推奨としています。(60fpsとした場合)各フレームを最大16ミリ秒とバジェットとなっていますが、ブラウザは各フレームをレンダリングをするのに約6ミリ秒かかるため、1フレームあたり10ミリ秒がガイドラインになってます。
・Idle 50ミリ秒
Idleはアイドル状態に実行されるJavaScriptの処理時間のことです。
アイドル状態とは一度ResponseやAnimation、Loadが終了して何らかのユーザーのアクションを待っている状態を指します。
モダンブラウザではJavaScriptの処理とユーザーからの何らかのアクションの受け取りは同一のメインスレッドで受け取ります。このためUI上では何も処理していないように見えて、裏側ではJavasScriptの実行している場合があります。この場合、ユーザーの入力の受け取りはJavaScriptの処理が終えてからになるため、遅延することになります。
・Load 1000ミリ秒
LoadはWebページのコンテンツの読み込みにかかる時間のことです。
1000ミリ秒以内に収めることが難しい場合は、キャッシュやローディングアイコン画面を表示して、リソースの読み込みを遅延することも求められます。
GoogleのRAIL ガイドラインでは、コンテンツ配信から5秒以内に操作可能状態がガイドラインになってます。理由はページの読み込みが遅いと、ユーザーは関心を失い、タスクが中断されたと感じます。5秒以内の目標値は3G接続時のモバイルデバイスに対しての目標値となっております。
Core Web Vitals
RAILは2015年 開発者向けカンファレンス「Google I/O 2015」にて発表されました。
しかし、2020年にGoogleが新しく発表した指標があります。
それがCore Web Vitals(コアウェブバイタル) になります。
Core Web VitalsはGoogleが設定しているサイトの健全性を示す重要指標であり、メディア上でのユーザー体験(UX)を定量的に評価した指標です。
Core Web Vitalsは4つの指標があります。
・Cumulative Layout Shift (累積レイアウトシフト数、CLS)
Webページの視覚的な安定性を測定するための指標になります。
ページのレイアウトの変化量が0.1であることが良好とされています。
例えば、ページのリンクをタップしよとしたら、突然広告が表示されて誤って広告をタップしてしまったり、記事を閲覧していたら、広告が少し遅れて表示され記事が少し下にずれる体験を指します。
https://web.dev/cls/
・Largest Contentful Paint (最大視覚コンテンツの表示時間、LCP)
ページのメインとなるコンテンツが表示されるまでの時間を示す指標になります。
ページの読み込みが開始されてから、LCPとなるコンテンツを2.5秒以内に表示することが良好であるとされています。
メインとなるコンテンツとは、ブラウザの表示範囲内で最も大きなコンテンツのことを指します。具体的には、img要素やvideo要素、背景画像を持つ要素、テキスト要素を含むブロックレベル要素などです。
https://web.dev/lcp/
・First Input Delay (初回入力までの遅延時間、FID)
ユーザーがページ内で最初にクリックやタップ、テキスト入力などのアクションを行った際の反応速度を測る指標になります。FIDは100ミリ秒以下にすることが求められています。
https://web.dev/fid/
・Interaction to Next Paint (次のペイントまでの時間、INP)
こちらは2022年5月に新しく発表された指標になります。
Webページ上でのユーザーが何らかしらの操作(タップやクリック、キーを押下などの操作)してからその結果を応答するまでの反応速度を測る指標になります。
INPは入力遅延時間、処理時間、表示遅延時間の3つのフェーズで構成された遅延時間の合計値が評価値になります。200ミリ秒以下であれば、良好とされています。
https://web.dev/inp/
・First Input DelayとInteraction to Next Paintの違い
First Input Delay(以下、FID)もInteraction to Next Paint(以下、INP)も応答性を測る指標でありますが、FIDとINPに違いがあります。
計測対象範囲と計測対象となる時間において違いがあります。
計測対象範囲
・FID: 最初のインタラクション
・INP: ページの読み込みを開始してからユーザーがページを離れるまでの全てのインタラクション
計測対象となる時間
・FID: 入力遅延時間のみ
・INP: 入力遅延時間、処理時間、表示遅延時間の合計
計測
パフォーマンスチューニンングにおいて、重要なのは計測することです。
そのために、計測ツールや計測ライブラリが必要になってきます。
計測ツール
・Lighthouse
Googleが無料で提供しているWebページを分析・診断するためのツールです。
下記の5つの項目ごとに、
・「Performance(パフォーマンス)」
・「Accessibility(アクセシビリティ)」
・「Best Practices(ベストプラクティス)」
・「SEO」
・「Progressive Web App(プログレッシブウェブアプリケーション)」
Google独自の基準でチェックし、各項目毎にスコアが表示され、改善するべき項目が表示されます。
利用方法は、Chrome Dev ToolsやChrome拡張機能、WebPageTest内などで利用できます。
・PageSpeedInsights
Googleが無料で提供しているWebサイトのパフォーマンス評価ツールです。
指定したURLのデスクトップ版とモバイル版の両方のWebサイトパフォーマンスを評価し、スコアと改善案をレポートしてくれます。
PageSpeedInsightsとLighthouseとの大きな違い
Lighthouse | PageSpeedInsights | 備考 | |
監査カテゴリ | パフォーマンス・アクセシビリティ・ベストプラクティス・SEO・PWA | パフォーマンスのみ | |
実行環境 | クライアント端末 | Googleが用意するサーバー | |
安定性 | 実行環境に依存 | 高い | Lighthouseは自前の環境で実行するのでネットワークの速度によって点数が前後します。PageSpeed Insightsの方が安定性はあります。 |
計測サービス
計測サービスでは、弊社でも使っているサービスをご紹介します。
・SpeedCurve
SpeedCurveは継続的にWebサイトのパフォーマンスデータを収集し、分析し、可視化することを売りにしているサービスであり、フロントエンドのパフォーマンス監視に特化したサービスです。フロントエンドのパフォーマンスの定期観測や定期的にパフォーマンスのデータの振り返り、蓄積されたパフォーマンスデータを元に改善に役立てられたりととても便利なサービスです。
終わり
以上、Webフロントエンド パフォーマンスとして重要な部分と最新のパフォーマンス指標をまとめてみました。
Webフロントエンド パフォーマンスの知識アップデートの参考になれば幸いです。
参考
・RAIL
https://web.dev/i18n/ja/rail/
・Web Vitals
https://web.dev/vitals/
・久保田光則著 (2017)「Webフロントエンド ハイパフォーマンス チューニング」技術評論社