- PageSpeed Insights
AIが翻訳した投稿です。
durumis AIが要約した投稿
- Webパフォーマンス測定ツール(PageSpeed Insights、Lighthouse)を活用してウェブサイトのパフォーマンスを改善すると、検索エンジンの表示に有利になり、Web Core Vitals指標が重要になります。
- CLS、LCP、FCP、FIDなどの指標改善のために、UIスケルトン、画像最適化、レンダリングをブロックする要素の削除、Webフォントの最適化、JavaScriptの非同期処理などを適用できます。
- 各指標の改善方法とともに、Webパフォーマンス向上のための様々な技術(gzip圧縮、Webワーカーなど)を紹介し、今後関連内容を深掘りしていく予定です。
Googleが提供するサイトを通じて
Webのパフォーマンスを簡単に測定することができます。
https://pagespeed.web.dev/
にURLを入力して測定するか、Chrome拡張機能でLighthouseをインストールして測定することができます。
指標を改善すると何がよいのだろうか?
検索エンジンのランキングでより上位に表示される可能性が高まります。SEOにより、サーバーサイドレンダリングが広く使用されていますが、
もし上記の性能指標が低いと、その効果は大きく低下するでしょう。
どのように改善するのか?
web.devサイトでは、各指標をどのように改善できるかが詳細に説明されています。
特に3つの指標がスコアに大きく影響しています。(Web Core Vitals)
指標を改善するために試したことを記録しておきたいと思います。
ローカルで測定するには?
export default () => { if (process.client && 'PerformanceObserver' in window) { let cumulativeLayoutShiftScore = 0; let largestContentfulPaint = 0; let firstInputDelay = 0; let firstContentfulPaint = 0;
// CLS const clsObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); entries.forEach((entry) => { if (!entry.hadRecentInput) { cumulativeLayoutShiftScore += entry.value; } }); }); // LCP const lcpObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); const lastEntry = entries[entries.length - 1]; largestContentfulPaint = lastEntry.startTime; }); // FID const fidObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); const firstEntry = entries[0]; firstInputDelay = firstEntry.processingStart - firstEntry.startTime; }); // FCP const fcpObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); const firstEntry = entries[0]; firstContentfulPaint = firstEntry.startTime; }); clsObserver.observe({ type: 'layout-shift', buffered: true }); lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true }); fidObserver.observe({ type: 'first-input', buffered: true }); fcpObserver.observe({ type: 'paint', buffered: true }); window.addEventListener('onload', () => { console.log('Final CLS Score:', cumulativeLayoutShiftScore); console.log('LCP:', largestContentfulPaint); console.log('FID:', firstInputDelay); console.log('FCP:', firstContentfulPaint); }); } };
上記のコードを挿入します。Nuxtの場合、pluginsに挿入してコンソールログを確認します。
Cumulative Layout Shift (CLS)
レンダリング中にレイアウトが変化する程度を測定したものです。
例えば、APIレスポンスで画像URLを受け取り、400x400の画像をレンダリングするページがあるとします。
あるレイアウトの位置は、画像がレンダリングされるにつれて400px移動するでしょう。
これは、ユーザーが予測しない移動であり、UXに悪影響を与えるだけでなく、ブラウザも画面をレンダリングする際に
間接的に悪影響を受けます。
改善するための簡単な方法として、2つあります。
1. UIスケルトンを適用する
- ほとんどのサイトでは、画像サイズまたはコンポーネントサイズに合わせて適切にスケルトンを描画しています。画面を開発する際にこの部分を考慮します。Vueの場合、v-ifとv-elseを活用して、各要素に合わせたスケルトンを描画します。
2. 高さを予約する
- スケルトンにスタイルが多すぎると、保守が複雑になり、逆効果になる可能性があります。単にレンダリングされる要素のmin-heightを指定するだけでも効果が期待できます。
- 反応型Webなど、画像サイズがデバイスによって異なる場合は、heightを固定的に指定することが難しいです。この場合は、最も小さいデバイスを基準にするか、vhやvwを活用することができます。
3. 画像要素にはwidthとheightを明示する
- 画像要素にwidthとheightを次のように入れることができます。
実際の画像サイズが400x400でなくても、ブラウザに画像の予想サイズを伝えます。
4. Webフォントによるレイアウト変化を防ぐためにfont-display: swapを使用する
- 代替フォントを指定することで、レイアウトのずれを防ぎます。
Largest Contentful Paint(LCP)
画面で最も大きな部分を占める要素がレンダリングされるまでに掛かる時間です。通常は画像ですが、直感的にローディング速度を速くすればよいです。
1. 画像サイズを小さくする。
- レンダリングサイズに比べて画像サイズが大きくなっていないか確認します。
- webpなどの拡張子で画像レンダリングを最適化します。webpは、損失圧縮を使用する場合、JPEGフォーマットよりも約30%ファイルサイズが小さく、無損失圧縮を使用する場合、pngよりも約20%サイズが小さくなります。
- スクロール位置に応じてロードされるLazy Loadingも検討できます。
2. キャッシュまたはCDNを活用する。
3. レンダリングをブロックする要素を削除する。
- ほとんどの測定指標に影響するため、必ず削除します。ブラウザは画面をレンダリングする際にheadタグ内のスクリプトを最初に取得してからレンダリングするため、headタグ内のスクリプト(一般的に外部スクリプト)が最初にレンダリングされる必要があるかどうかを確認します。これに関して、asyncとdeferタグを使用すると、簡単に管理できます。
* head内のスクリプト属性については、後日別の記事で書きたいと思います。
4. バンドルサイズを最小化する。
- 画像のレンダリング速度が遅いこととは別に、サーバーからの転送が遅い場合は、これを改善する必要があります。
nginxなどのプロキシサーバーを使用している場合は、gzip圧縮を活用できます。
* nginxの設定については、後日別の記事で書きたいと思います。
First Contentful Paint(FCP)
ページで最初のコンテンツがレンダリングされる時点を意味します。
1. 同様に、レンダリングをブロックする要素を削除します。
2. HTMLサイズを最小化する。
- 無駄にdivタグで囲みすぎると、非常にネストしたツリーが生成され、ファイルサイズも大きくなります。
3. 外部Webフォントが問題となる可能性があります。font-display: swap;を積極的に活用して、デフォルトフォントを先にレンダリングします。
First Input Delay(FID)
ユーザーがページで最初の入力(クリック、スクロールなど)を行ったときに、ブラウザがそれを処理するのにかかる時間を意味します。ボタンを押しても反応しない場合があります。実際には反応がないのではなく、APIレスポンスを待っている可能性があります。
1. 非同期をうまく活用して、JavaScriptメインスレッドが重い処理にブロックされないように開発します。
2. メインスレッドとは別に、Webワーカーを使用して別の処理を実行できます。
* Webワーカーについては、後日また別の記事で書きたいと思います。
文字数制限のため、これにて終了とさせていただきます。