Next.jsを利用したEコマースWebサイトでのCLS問題の解決(ケーススタディ)
公開: 2022-03-10フェアプライスは、シンガポールで最大のオンライン食料品店の1つです。 私たちは、ユーザーのオンラインショッピング体験を向上させる機会の分野を継続的に探しています。 パフォーマンスは、デバイスやネットワーク接続に関係なく、ユーザーが快適なユーザーエクスペリエンスを確実に享受できるようにするための主要な側面の1つです。
Webページのライフサイクル中のさまざまなポイント(TTFB、 domInteractive
、 onload
など)を測定する多くの主要業績評価指標(KPI)がありますが、これらのメトリックは、エンドユーザーがページをどのように体験するかを反映していません。
エンドユーザーの実際のエクスペリエンスに密接に対応するいくつかのKPIを使用したかったので、これらのKPIのいずれかがうまく機能していない場合、エンドユーザーエクスペリエンスに直接影響することがわかります。 ユーザー中心のパフォーマンスメトリクスがこの目的に最適であることがわかりました。
FCP、LCP、FID、CLSなど、ページのライフサイクルのさまざまなポイントを測定するためのユーザー中心のパフォーマンスメトリックが多数あります。 このケーススタディでは、主にCLSに焦点を当てます。
CLSは、ページのロードを開始してからアンロードされるまでの間に発生するすべての予期しないレイアウトシフトの合計スコアを測定します。
「「
したがって、ページのCLS値を低くすると、ユーザーのフラストレーションを引き起こすランダムなレイアウトシフトがなくなります。 Barry Pollardは、CLSに関する優れた詳細な記事を書いています。
製品ページでCLSの問題をどのように発見したか
CLSを測定するためのパフォーマンスの合成テストツールとして、LighthouseとWebPagetestを使用しています。 また、Web-vitalsライブラリを使用して、実際のユーザーのCLSを測定します。 それとは別に、Google Search Console Core Web Vitals Reportセクションをチェックして、いずれかのページで発生する可能性のあるCLSの問題を把握します。 レポートセクションを調べていると、製品の詳細ページの多くのURLに0.1を超えるCLS値があり、そこでいくつかの主要なレイアウトシフトイベントが発生していることがわかりました。
さまざまなツールを使用したCLS問題のデバッグ
製品の詳細ページにCLSの問題があることがわかったので、次のステップは、どの要素が原因であるかを特定することでした。 最初に、合成テストツールを使用していくつかのテストを実行することにしました。
そこで、灯台を走らせて、大きなレイアウトシフトを引き起こしている可能性のある要素を見つけることができるかどうかを確認しました。CLSは.004と報告されており、これは非常に低い値です。
Lighthouseレポートページには診断セクションがあります。 また、CLS値が高くなる要素は示されていません。
次に、WebpageTestを実行し、フィルムストリップビューを確認することにしました。
この機能は、どの時点でどの要素がレイアウトをシフトさせたかを知ることができるため、非常に役立ちます。 しかし、レイアウトの変化が強調表示されているかどうかを確認するためにテストを実行したとき、巨大なLCSに寄与するものは何もありませんでした。
CLSの癖は、ページの存続期間全体にわたって個々のレイアウトシフトスコアを記録し、それらを追加することです。
「「
注: CLSの測定方法は、2021年6月から変更されています。
LighthouseとWebpageTestは、大きなレイアウトシフトをトリガーした要素を検出できなかったため、これは、おそらくユーザーの操作が原因で、最初のページの読み込み後に発生したことを意味します。 そこで、ユーザーがページを操作しているときにページにCLSを記録できるため、Web VitalsGoogleChrome拡張機能を使用することにしました。 さまざまなアクションを実行した後、ユーザーが画像拡大機能を使用すると、レイアウトシフトスコアが増加していることがわかりました。
画像上でマウスオーバーが発生しているときにレイアウトシフトが発生しているかどうかを相互検証するために、https://web.dev/cls/の以下のコードスニペットを使用しました。これにより、レイアウトシフトが発生したときにconsole.log
が追加されます。
let cls = 0; new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { if (!entry.hadRecentInput) { cls += entry.value; console.log('Current CLS value:', cls, entry); } }}).observe({type: 'layout-shift', buffered: true});
さらに調査したところ、ASDAも同様の問題に直面しており、Chromeで問題が発生していることがわかりました。
根本的な原因
製品の詳細ページで、ユーザーはマウスを製品画像の上に移動して、実際の製品画像の横に画像のズームされたセクションを表示できます。このビデオは、私たちが話していることを正確に示しています。
画像拡大機能は、ユーザーが製品のルックアンドフィールを取得し、購入したい製品の正しいバリエーションであることを確認するのに役立ちます。
この画像拡大機能を構築するために、 react-image zoom
ライブラリを使用しました。
Image Magnifyライブラリには通常、レンズ(マウスが画像内を移動すると移動する正方形)があります。 このレンズはマウスの動きで上下の位置が変わるため、CLSをトリガーするレイアウトシフトとして検出されています。 ライブラリページと他の同様のreactライブラリ( react-image-magnify
、 react-image-zoom
、 react-image-magnifiers
)を確認したところ、すべてのライブラリで同じCLSの問題が発生していることがわかりました。
修正方法
react-image-zoom
がjs-image-zoom
ライブラリを使用していることに気づきました。 そのため、問題を修正するためにjs-image zoom
ライブラリを変更する必要がありました。
解決策は非常に簡単です。 マウスが製品画像上を移動している間、画像レンズ要素はその左右の位置を変更することによって移動します。 この問題を修正するために、要素を新しいレイヤーに移動するtransform translate
を使用しました。つまり、この新しいレイヤーで行われる移動によって、レイアウトがシフトすることはなくなりました。
また、このライブラリを使用している他の開発者がCLSの問題を取り除くことができるように、元のリポジトリへのPRを作成しました。
変更の影響
コードが本番環境にデプロイされた後、CLSは製品の詳細ページで修正され、CLSの影響を受けるページ数は98%削減されました。
transform
を使用したので、画像がユーザーにとってよりスムーズなエクスペリエンスを拡大するのにも役立ちました。
注: Paul Irishは、このトピックに関する優れた記事を書いています。
CLS用に行ったその他の重要な変更
また、CLSに寄与する、当社のWebサイトの多くのページで直面した他の問題もいくつかあります。 それらの要素とコンポーネントを調べて、それらから生じるレイアウトの変化をどのように軽減しようとしたかを見てみましょう。
Webフォント:
フォントの読み込みが遅いと、コンテンツが点滅するためユーザーの不満が生じ、レイアウトが多少ずれることもあります。 これを最小限に抑えるために、いくつかの変更を行いました。- サードパーティのCDNからロードする代わりに、フォントをセルフホストしました。
- フォントをプリロードします。
- オプションでfont-displayを使用します。
画像:
画像に高さまたは幅の値がない場合、画像が読み込まれると、画像の後の要素がシフトします。 これは、CLSの主要な貢献者になることになります。 Next.jsを使用しているため、next/images
という組み込みの画像コンポーネントを利用しました。 このコンポーネントには、画像に関連するいくつかのベストプラクティスが組み込まれています。<img>
HTMLタグの上に構築されており、LCPとCLSの改善に役立ちます。 このRFCを読んで、それを使用することの主な機能と利点を見つけることを強くお勧めします。無限スクロール:
当社のウェブサイトでは、商品リストページが無限にスクロールします。 そのため、最初に、ユーザーがページの一番下までスクロールすると、次のデータセットが読み込まれる前に数分の1秒間フッターが表示され、これによりレイアウトがシフトします。 これを解決するために、いくつかの手順を実行しました。- ユーザーがリストの一番下に到達する前でも、APIを呼び出してデータをロードします。
- ロード状態のために十分なスペースを予約し、ロード状態の間に製品スケルトンを表示します。 そのため、ユーザーがスクロールすると、製品が読み込まれている間、フッターが数秒間表示されません。
Addy Osmaniがこのアプローチに関する詳細な記事を書いていますが、これを確認することを強くお勧めします。
重要なポイント
- LighthouseとWebpageTestは、ページの読み込みまでに発生するパフォーマンスの問題を検出するのに役立ちますが、ページの読み込み後はパフォーマンスの問題を検出できません。
- Web Vitals拡張機能は、ユーザーの操作によってトリガーされたCLSの変更を検出できるため、ページのCLS値が高いが、LighthouseまたはWebpageTestが低いCLSを報告する場合、WebVitals拡張機能は問題を特定するのに役立ちます。
- Google検索コンソールのデータは実際のユーザーのデータに基づいているため、ページのライフサイクルの任意の時点で発生する可能性のあるパフォーマンスの問題を指摘することもできます。 問題が検出されて修正されたら、レポートセクションを再度確認すると、パフォーマンス修正の有効性を確認するのに役立ちます。 変更は、数日以内にWebバイタルレポートセクションに反映されます。
最終的な考え
CLSの問題のデバッグは比較的困難ですが、ページの読み込みまで(Lighthouse、WebPageTest)、Web Vitals拡張機能(ページの読み込み後)にさまざまなツールを組み合わせて使用すると、問題を特定するのに役立ちます。 また、さまざまなシナリオをカバーするために多くの活発な開発が行われている指標の1つであり、これは、測定方法が将来変更されることを意味します。 今後の変更については、https://web.dev/evolveing-cls/をフォローしています。
私たちに関しては、他のコアWebバイタルの改善にも継続的に取り組んでいます。 最近、レスポンシブ画像のプリロードを実装し、WebP形式で画像の提供を開始しました。これにより、画像のペイロードが75%削減され、LCPが62%削減され、Speed Indexが24%削減されました。 LCPとSpeedIndexを改善するための最適化の詳細を読むか、エンジニアリングブログをフォローして、私たちが行っている他のエキサイティングな作業について知ることができます。
製品ページでCLSの問題をデバッグし、 next/images
の実装の癖を解決するのを手伝ってくれたAlexCastleに感謝します。