ウェブパフォーマンス向上のためにフロントエンドで考えるべきこと

# はじめに
ウェブサイト・アプリケーションにおいて表示が遅くてアクセスを諦めたという経験はありませんか？
これはサービスを提供する側は機会損失、利用する側は目的を達成できず時間を無駄にします。両者とも良いことはありません。
Googleの見解ではページの読み込み速度が1秒から3秒に増えるとモバイルサイト訪問者の直帰率は32%、5 秒に増えると90％、6秒に増えると106%になるとのことです。
こういったことを防ぎ、ユーザー体験をより良いものにするために必要なのがウェブパフォーマンス向上を目的としたチューニングです。

参照: [Find Out How You Stack Up to New Industry Benchmarks for Mobile Page Speed](https://www.thinkwithgoogle.com/intl/en-ca/marketing-strategies/app-and-mobile/mobile-page-speed-new-industry-benchmarks/)

## 本記事について
- フロントエンドでパフォーマンスチューニングを実施するための準備や心構えについてまとめた記事です
- 「ウェブパフォーマンスの重要性」「チューニングを実施するにあたり知っておくべきこと・考えるべきこと」をメインに記載しています
- フロントエンドでパフォーマンスチューニングを実施する前に必要な事前知識を身につけることを目的としています

※ 具体的なチューニング方法については本記事では扱っていません。チューニング方法については別途投稿予定です。

# ウェブパフォーマンス
ウェブパフォーマンスについて、[ウェブパフォーマンスとは - ウェブ開発を学ぶ | MDN](https://developer.mozilla.org/ja/docs/Learn/Performance/What_is_web_performance)で以下のように説明されています。

> ウェブパフォーマンスとは、遅い処理を速く見せることも含めて、ウェブサイトを速くすることです。サイトがすぐに読み込まれるか、ユーザーがすぐに操作を始めることができるか、何かの読み込みに時間がかかっている場合には安心感のあるフィードバック (ローディングスピナーなど) を提供しているか。スクロールやアニメーションはスムーズか。

また、以下のようにも説明されています。

> ウェブパフォーマンスはウェブサイトまたはウェブアプリケーションの客観的な測定結果とユーザーによって知覚される体験です。

端的に述べると、ユーザーの操作に対するウェブページやコンテンツの応答速度となります。
ユーザーの操作の代表例として以下があります。

- ブラウザのアドレスバーからURLを入力してウェブページを表示させる
- ボタンをクリック
- スクロール
- フォーム入力
- etc...

これらの操作に対してウェブページやコンテンツは何らかの応答を返します。このやりとりをインタラクションといいます。

## ウェブパフォーマンスの重要性
インタラクションを繰り返すことによってユーザーはウェブ上での目的を達成します。
このインタラクションがスムーズに行われないと残念なユーザー体験になってしまいます。
例えば、読み込み時間が長くて画面が表示されずアクセスを諦めたり、スクロールすると画面がガタつき見づらくて閲覧をやめたりなどです。
ユーザーがウェブ上での目的をスムーズに達成できれば、時間を節約できます。そして節約した時間分を別のことに費やすことができます。つまりウェブパフォーマンスを改善し、向上させることでユーザーの時間やリソースを節約させることができます。その結果、ユーザーを豊かにできる可能性があります。
ゆえにウェブパフォーマンスの向上が重要になります。
そして、それを実現するために必要なのがパフォーマンスチューニングです。
パフォーマンスチューニングはウェブにアクセスするデバイス、通信環境ごとにそれぞれ最適化を行います。
近年、デバイスや通信環境は多様化しているためパフォーマンスチューニングは必要不可欠です。

# チューニングを実施する前に理解しておくべきこと
パフォーマンスチューニングを実施する前に、以下の３点については最低限理解しておくべきです。

- ブラウザのレンダリング
- ウェブパフォーマンスの指標
- ウェブパフォーマンスの可視化と計測

これらを理解することにより、ボトルネックの特定やチューニングの方針を決めるのに役立ちます。結果、チューニングをスムーズに実施することができます。

## ブラウザのレンダリング
ブラウザのレンダリングの仕組みを理解することにより、レンダリングのどの段階で問題が発生しているのかを判断できます。それはボトルネックの特定に繋がり、解消の手がかりにもなります。
ブラウザのレンダリングは Loading（リソース読み込み）、Scripting（JavaScript実行）、Rendering（レイアウトツリー構築）、Painting（レンダリング結果の描画）という4つの処理を経て行われます。

図：レンダリングの流れ ![img-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584922/50a8e3ae-2391-dad1-eef8-1d12cd792665.png)

### Loading（リソース読み込み）
LoadingではHTMファイルやCSSファイル、JavaScriptファイル、画像ファイルをダウンロードします。
ダウンロード後、HTMLはDOM（Document Object Model）ツリー、CSSはCCSOM(CSS Object Model)ツリーを構築します。

### Scripting（JavaScript実行）
ScriptingではJavaScriptを実行します。
実行はブラウザのJavaScriptエンジンがJavaScriptのコードをコンパイル（機械語へ変換）してから行われます。また、JavaScriptファイルが読み込まれたタイミングやDOMイベントが発生した際に行われます。

### Rendering（レイアウトツリー構築）
RenderingはDOMツリーとCSSOMツリーを精査して描画に必要なレイアウトツリーを構築します。
レイアウトツリーはDOM要素にどのCSSルールセットが適用されるかの計算、レイアウト情報（要素の横幅や縦幅、マージン、パディングなど）の計算を経て構築されます。

### Painting（レンダリング結果の描画）
Paintingはレンダリング結果を描画します。
構築したレイアウトツリーをもとにレイヤー単位でピクセルを描画し、このレイヤーを合成してレンダリングが完了します。また、ピクセルを描画することによって初めて目視することができます。

## ウェブパフォーマンスの指標
ウェブパフォーマンスを改善するにあたり、結果を判断する指標は必要不可欠です。
パフォーマンス指標を利用すれば、どの部分をどこまでチューニングするのか取捨選択できるようになります。
また、チームでパフォーマンス改善に取り組む際もチーム内での共通解となります。
大切なのは指標の数値をクリアすることだけに囚われず、本来の目的であるユーザーの体験を向上させるためにパフォーマンスを改善するということを忘れてはいけません。
ここではWeb VitalsとRAILという代表的な２つのパフォーマンス指標を紹介します。

### Web Vitals
Web VitalsはGoogleが定義したUX指標です。
経験や知識がないとパフォーマンスの指標を独自に設定するのは難しいです。
その点、既存の優れた指標であるWeb Vitalsを利用するのはとても有効であり、積極的に活用するべきです。特別なツールを使用せず、Google Choromeのデベロッパーツールで簡単に数値を確認できるのもメリットです。
また、Web Vitalsの指標は毎年アップデートされます。指標が変わり続ければ改善点も変わるので定期的なチューニングが必要になり、チューニングが習慣化することも期待できます。

Web Vitalsで重要視されているものは以下の3点です。

- Largest Contentful Paint
- First Input Delay
- Cumulative Layout Shift

参照: [Google Developers Japan: Web Vitals の概要: サイトの健全性を示す重要指標](https://developers-jp.googleblog.com/2020/05/web-vitals.html)

#### Largest Contentful Paint
ページの表示速度を測る指標です。
具体的には最大コンテンツ（ページのメイン部分）の描画、それを読み込み表示する時間を示す指標です。
2.5秒以内が良評価となります。

#### First Input Delay
ユーザーの応答性を測る指標です​。
コンテンツが表示され、操作できるようになるまでの時間が1秒以内が良評価となります。
JavafScriptの読み込みが大きく影響します。

#### Cumulative Layout Shift
視覚の安定性を測る指標です​。
ロードしたあとに表示がずれたり、最初に画像が表示されず少ししてから表示され、その分レイアウトがずれるなど予期せぬレイアウトの崩れを定量化します。0.1以下が良評価となります。
画像やiframeなどの縦横幅を指定していないことが原因で発生します。

### RAIL
RAILはGoogleの開発者Ilya Grigorik氏が提唱したパフォーマンス指標です。
Response, Animation, Idle, Loadの頭文字から名づけられています。
ユーザーの操作（タップ、スクロール、ロードなど）に対してのパフォーマンス指標として役立ちます。

| 項目                        | 基準時間   | 内容                                                                                                          |
| --------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------- |
| RESPONSE（応答）            | 100ミリ秒 | ユーザーの操作に対して目に見える応答をするまでの時間 |
| Animation（アニメーション） | 16ミリ秒  | アニメーションにおける各フレームの処理時間                                 |
| Idle（アイドル処理）        | 50ミリ秒  | アイドル状態に実行されるJavaScriptの処理時間                                                               |
| Load（読み込み）            | 100ミリ秒 | ウェブページのコンテンツの読み込みにかかる時間                                                                  |

※ アイドル状態とは、Response、Animation、Load が終了してから何らかのユーザーのアクションを待っている状態

参照: [Measure performance with the RAIL model](https://web.dev/rail/)

## ウェブパフォーマンスの可視化と計測
計測の重要性と代表的な計測ツールについて紹介します。
パフォーマンスチューニングにおいて計測は最重要項目です。
「推測するな、計測せよ」というUNIX格言もあります。
まったく予期せぬ部分でパフォーマンス上の問題が発生することがあります。
その際に、「おそらくここがパフォーマンス上問題になっている」「自分が構築したものだから、どのように動作するか知っている」という推測や思い込みは捨てるべきです。
私自身も推測で実施したチューニングが見当違いだった、部分的には改善できたが全体のパフォーマンスが下がるといった失敗経験をしたことがあります。
さらに推測で実施したチューニングは、コードの保守性や拡張性も失われる可能性もあります。
このような事態を避けるためにパフォーマンス上問題になっている部分を計測する必要があります。
計測しボトルネックを特定し、その部分に効果的なチューニングを実施します。
また、計測の際に可視化することも重要です。見えないものは測れない、測れないものは改善できません。
例えば、Google Choromeデベロッパーツールのタイムライン機能はグラフや数値化など分かりやすく可視化してくれます。
また、以下のツールも同様です。

- PageSpeed Insights​
- Lighthouse CI​
- Chrome User Experience Report
- WebPageTest

### PageSpeed Insights​
Googleが提供するスコア測定ツールです。
モバイル・デスクトップごとに、0～100のスコアでページ表示速度を判定してくれます。
さらに、Web Vitalsの測定も実施してくれます。
参照: [PageSpeed Insights](https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect&hl=ja)

### Lighthouse
Google Chromeの拡張機能を使って使用します。PWAの項目、表示速度、サイトをスクロールする際のパフォーマンスなどを評価判定します。
Lighthouse CIというツールもあり CI実行のタイミングでトリガーさせることが出来るツールです。Circle CI, Github Actions, Jenkinsなどに対応しています。

### Chrome User Experience Report(CrUX)
Googleが提供しているUXやパフォーマンスを確認するためのツールです。
Web Vitalsなどの１ヶ月ごとのデータをレポートとして得ることができます。
継続的に計測を実施する際に役立ちます。

### WebPageTest
ウェブサイトのURLを指定して計測できるツールです。
各ファイルのダウンロード時間、JSの実行時間を計測できます。
回線速度やデバイスなど仮想環境で条件を指定して計測ができたり、APIを取得してGoogleのスプレッドシートと連携したりなど機能が豊富です。

参照: [WebPageTest - Website Performance and Optimization Test](https://www.webpagetest.org/)

### 計測ツールは組み合わせて使う
基本的にはGoogle Choromeデベロッパーツールと先述したものを組み合わせて十分な計測ができるはずです。  
例えば以下の手順を想定します。

1. 継続的に計測
2. 計測結果に問題があれば、計測の対象範囲を徐々に小さくしボトルネックを特定
3. チューニングを実施
4. チューニングの結果、パフォーマンスが改善されているか計測

１ではCrUX、２ではWebPageTestとGoogle Chromeデベロッパーツール、4ではPageSpeed Insights​といった組み合わせで使います。
これは一例ですが様々な使い分けや組み合わせで柔軟に計測可能です。
また、SpeedCurveというSaas型パフォーマンス計測サービスもあります。パフォーマンス計測、時系列の計測を定期的に行うことができ高機能です。

参照: [SpeedCurve | Website Performance Monitoring](https://speedcurve.com/)

# ウェブパフォーマンスに対する考え方
ウェブパフォーマンスを向上させる目的はユーザーの体験をより良いものにするためです。
そのために、フロントエンドからのアプローチとしてモダンな技術を利用することが推奨されます。
それは、パフォーマンスにおけるベストプラクティスを組み込んで提供してくれるケースが多いからです。
例えばNext.jsやNuxt.js​といったJavaScriptフレームワークです。
Next.jsの例を紹介すると、以下の画像最適化を行う仕組みを提供しています。

- 画像を閲覧デバイスに応じてリサイズして表示してくれる（元画像が大きくともスマホでは小さくリサイズされた画像を表示）​
- PNGやJPEGなどの形式の画像を自動でWebPに変換（WebP対応ブラウザでのみWebPを読み込む）​
- 画像にwidthとheight属性を指定していても、レスポンシブ対応可能（画像の縦横比が崩れない）​
- 遅延ロード（loading="lazy"属性）に対応

参照: [next/image | Next.js](https://nextjs.org/docs/api-reference/next/image)

運用中におけるパフォーマンス改善も大切ですが、設計・実装中からパフォーマンスを意識し、よく調べた上でモダンな技術を取り入れるのは有効的です。
最後にウェブパフォーマンスに関する知見やチューニング技術を属人化せず、共有することが大切だと実感しています。
誰か1人ができるのではなく、関わるチームの全員が計測・分析・チューニングができる。パフォーマンス改善が文化になるのが理想です。  

# 参考文献

この記事は以下の情報を参考にして執筆しました。

- [久保田光則, Webフロントエンドハイパフォーマンスチューニング, 技術評論社, 2017年.](https://gihyo.jp/book/2017/978-4-7741-8967-3)