IntersectionObserver APIを使った速度改善について

こんにちは、Cake.jp技術部の福井です。

はじめに

ウェブページの速度改善を行う中で、IntersectionObserver APIを利用しました。この記事では、どのようにこのAPIを活用してパフォーマンスを改善したかについて詳しく解説します。

改善前の状態と背景

前提

Cake.jpの商品ページは縦長のスクロールが必要なサイトです。デザインを変更することによる、DOMサイズの縮小を行わない方針です。

速度の問題点

商品ページを表示する速度に当初はFCP(First Contentful Paint)が8.8秒かかっており、ユーザー体験に悪影響を与えていました。特に、ページの初期描画時に大きいサイズのDOMを一度に読み込むことで、表示が遅れてしまいました。

FCPとは?ページのコンテンツが最初に描画されるまでの時間を測る指標です。

▼詳しくはこちら: FCPの説明

web.dev

技術スタック

  • 使用技術: JavaScript
  • パフォーマンス問題の具体例: 初期ロード時に要素が表示されるまでに時間がかかる、ボタンを押しても反応しない

改善のアプローチ

私はFCPのスコアが悪い理由として、DOMサイズが大きすぎることに着目しました。DOMサイズ削減のため、ファーストビューに関係ないDOMを非同期で読み込む方法を検討しました。 非同期で読み込む方法として、ある特定の地点に到達したらイベントが発火するIntersection Observer APIを採用し、ユーザの動作によってファーストビューに関係ないDOMを取得するかどうかを決定することとしました。

IntersectionObserver APIとは

概要

IntersectionObserver APIは、要素がビューポートや祖先要素と交差する状態を非同期で監視するためのインターフェイスです。これにより、ユーザーが要素に到達するタイミングを検知し、適切なアクションを実行できます。

▼詳しい説明はこちら: MDN Web Docs - IntersectionObserver developer.mozilla.org

IntersectionObserver APIを導入できるかどうかの3つのステップ

  1. ファーストビュー外に多くの要素があることを確認する

    • 理由: ファーストビューにある要素をIntersectionObserver APIで遅延読み込みしても、恩恵をあまり受けることができないため。ファーストビュー外の要素による効果がより大きい。
  2. ファーストビュー外の要素を非表示にしたときに表示速度を向上できることを確認する

    • 理由: DOMを描画しないことで初期描画にかかる時間を軽減できるかどうかを検証するため。非表示の要素が後からロードされることで、ページの初期表示が迅速になることを確認。
  3. 全てのブラウザに対応しているオプションが利用可能であることを確認する
    • 理由: 一部のブラウザで対応していない場合、表示したい要素が正しく表示されない可能性があるため。全ブラウザ対応のオプションが利用可能であれば、互換性の問題を回避し、全ユーザーに一貫した体験を提供できる。

「IntersectionObserver API」を用いて改善することができると分かったら、次にどのように改善していくかを以下の3つのステップに整理しました。

  1. どこまで情報を非同期で表示するのかを決める
  2. 1で決めた箇所で、ソースを分割し、コンポーネントを別のエンドポイントで呼び出せるようにする
  3. ユーザーのスクロール位置に応じて、必要なコンポーネントを遅延ロードする

今回は、3番目の「IntersectionObserver API」を使用したアプローチについて詳しく見ていきます。

IntersectionObserverの適用とその効果

基本的なコード例

以下は、IntersectionObserver APIの基本的な使い方の例です。

    // IntersectionObserverのインスタンスを作成
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                // 要素がビューポートに入った時の処理
                entry.target.classList.add('visible');
            }
        });
    });
    // 監視する要素を指定
    const elements = document.querySelectorAll('.lazy-load');
    elements.forEach(element => {
        observer.observe(element);
    });

設定のカスタマイズ

  • root: 監視するビューポートの要素(省略するとデフォルトでビューポート全体)
  • rootMargin: 監視する領域のマージン
  • threshold: 要素が交差する割合(0から1の値)

具体的な実装方法

ユーザーが特定のスクロール位置に到達したときに、必要なコンポーネントを遅延ロードすることで、初期描画の速度を改善しました。これにより、ページの表示速度が当初の8.8秒から3.8秒に短縮されました。

測定方法

計測には、PageSpeed Insightsの「低速4G」設定を使用。以下のツールで測定を行いました。

  • ツール: Pagespeed Insights、Lighthouse
  • 改善前と改善後の比較: FCPの指標を使用

PageSpeed Insightsとは? モバイル端末やパソコン向けのページの実際のパフォーマンスに関するレポートと、そうしたページの改善方法を確認できます。

▼詳しくはこちら:PageSpeed Insightsの説明 developers.google.com

注意点と考慮事項

  • パフォーマンスのトレードオフ: Intersection Observerを使うことで、初期ロード時に一部のリソースの遅延が発生する可能性があるため、適切に調整する必要があります。

  • ブラウザサポート: Intersection Observer APIのサポート状況について確認することを推奨します。一部のオプションではSafariFirefoxなどのブラウザでのサポートが限られています。

まとめ

IntersectionObserver APIを活用することで、ページのパフォーマンスを大幅に改善することができました。今後は、さらに異なるシナリオでの応用や、他のパフォーマンス改善手法との組み合わせを検討していきたいと考えています。