performance-and-web-vitals について
Performance and Web Vitalsは、ウェブページの性能を評価・改善するためのリファレンススキルです。LighthouseやCore Web Vitalsに加え、画像、フォント、JavaScriptの確認方法を扱います。
主な機能
- 01Lighthouse監査のガイド
- 02LCP、CLS、INPの解説
- 03画像読み込みとサイズの助言
- 04ウェブフォント表示のガイド
- 05Lighthouse CIのチェック
活用シーン
- 01Lighthouseでページを監査
- 02レイアウトシフトや操作遅延の調査
- 03画像とフォントの読み込み確認
- 04CIで性能低下を検出
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dembrandt/ dembrandt-skills --skill performance-and-web-vitalsインストール後、Claude Code で/performance-and-web-vitalsを入力して読み込まれたか確認します。
詳細
パフォーマンスと Web Vitals
Lighthouse 監査を実行する
# CLI audit — outputs JSON and HTML report
npx lighthouse https://example.com --output html --output-path ./lighthouse-report.html
# Headless, useful in CI
npx lighthouse https://example.com --chrome-flags="--headless" --output json --output-path ./report.json
# Audit specific categories only
npx lighthouse https://example.com --only-categories=performance,accessibility,seo
または、Chrome DevTools → Lighthouse タブ → ページ読み込みを分析 を開きます。
目標スコア:
| カテゴリ | 目標 |
|---|---|
| パフォーマンス | ≥ 90 |
| アクセシビリティ | 100 |
| ベストプラクティス | ≥ 95 |
| SEO | ≥ 95 |
Core Web Vitals
LCP — 最大コンテンツ描画
メインコンテンツはどれくらい速く表示されますか?
目標:≤ 2.5s
LCP は、最も大きな表示要素(ヒーロー画像、見出し、動画のポスター)が描画されるタイミングを測定します。ユーザーが「ページは読み込まれたか」と感じる指標です。
よくある原因と対策:
| 原因 | 対策 |
|---|---|
| 最適化されていないヒーロー画像 | WebP/AVIF を使用し、適切なサイズにして、fetchpriority="high" を指定します |
| 画像がプリロードされていない | <link rel="preload" as="image" href="hero.webp"> |
| 描画をブロックする CSS/JS | 重要でない JS は遅延実行し、重要な CSS はインライン化します |
| サーバーの応答が遅い | CDN、キャッシュヘッダー、エッジ配信を使用します |
| Web フォントが描画をブロックしている | font-display: swap または optional を使用します |
<link rel="preload" as="image" href="hero.webp" fetchpriority="high">
<img src="hero.webp" alt="..." fetchpriority="high" width="1200" height="600">
LCP 画像には loading="lazy" を使用しないでください。最も重要な描画が遅れてしまいます。
CLS — 累積レイアウトシフト
読み込み中にコンテンツが動き回りますか?
目標:≤ 0.1
CLS は、予期しないレイアウトシフト、つまり描画後にコンテンツが移動することを測定します。寸法が指定されていない画像、遅れて読み込まれる広告、フォントの切り替え、既存コンテンツの上に挿入される動的コンテンツなどが原因です。
よくある原因と対策:
| 原因 | 対策 |
|---|---|
| 幅と高さが指定されていない画像 | <img> に必ず width と height を指定します |
| Web フォントの切り替え | font-display: optional を使用するか、フォントをプリロードします |
| ファーストビューより上にある動的コンテンツ | コンテナーに min-height を設定してスペースを確保します |
| 遅れて読み込まれる広告や埋め込みコンテンツ | 広告枠に固定寸法を指定してスペースを確保します |
| レイアウトをずらすアニメーション | transform のみをアニメーションさせ、top/left/width/height は決してアニメーションさせません |
<img src="product.jpg" width="400" height="300" alt="...">
/* Reserve space for dynamic content */
.ad-slot { min-height: 250px; }
/* Animate transform, not layout properties */
.slide-in { transform: translateY(0); transition: transform 300ms; }
INP — 次の描画までのインタラクション
ユーザー入力に対して、ページはどれくらい速く応答しますか?
目標:≤ 200ms
INP は、ユーザーの操作(クリック、タップ、キーボード入力)から次の視覚的な更新までの遅延を測定します。INP が高いと、UI の動作が遅かったり、フリーズしたりするように感じられます。
よくある原因と対策:
| 原因 | 対策 |
|---|---|
| メインスレッドでの負荷の高い JS | 小さなタスクに分割し、requestIdleCallback を使用します |
| 大きなイベントハンドラー | スクロールとサイズ変更のハンドラーにデバウンス/スロットルを適用します |
| 同期的な DOM 更新 | requestAnimationFrame で DOM 書き込みをまとめます |
| サードパーティスクリプトによるブロック | サードパーティスクリプトを async または defer で読み込みます |
| React の再レンダリング | useMemo、useCallback、React.memo でメモ化します |
画像
画像は、ほとんどのページでパフォーマンスを向上させる最も大きな要素です。
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" width="800" height="600" alt="..." loading="lazy">
</picture>
<img
srcset="image-400.webp 400w, image-800.webp 800w, image-1200.webp 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
src="image-800.webp"
alt="..."
width="800"
height="600"
loading="lazy"
>
ルール:
- 必ず
widthとheightを設定します — CLS を防止します - ファーストビューより下では
loading="lazy"を使用し、LCP 画像には使用しません - WebP または AVIF を配信します — 通常、JPEG より 30~50% 小さくなります
- 表示サイズに合わせて画像のサイズを調整します — 400px の枠に 2000px の画像を配信しないでください
- 可能な場合は、自動形式変換に対応した CDN を使用します
フォント
Web フォントは、適切に処理しないと描画をブロックします。
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preload" href="/fonts/brand.woff2" as="font" type="font/woff2" crossorigin>
@font-face {
font-family: 'Brand';
src: url('/fonts/brand.woff2') format('woff2');
font-display: swap; /* show fallback immediately, swap when loaded */
/* font-display: optional; — never swap, use fallback if not cached */
}
font-display: swap— 見出しに適しており、CLS は許容範囲ですfont-display: optional— CLS がゼロになり、キャッシュされている場合にのみフォントが使用されます(本文に最適です)- 実際に使用する文字にフォントをサブセット化します — ファイルサイズを 60~80% 削減できます
JavaScript
<script src="analytics.js" defer></script>
<script src="chat-widget.js" async></script>
<script type="module" src="app.js"></script>
defer:HTML の解析後に、順番どおりに実行します — ほとんどのスクリプトに使用しますasync:ダウンロード後すぐに、順不同で実行します — 独立したスクリプト(アナリティクスなど)に使用します<head>内の同期的な<script>でメインスレッドを決してブロックしないでください
Lighthouse CI(自動監査)
デプロイ前にリグレッションを検出できるよう、CI で Lighthouse を実行します。
# Install
npm install -g @lhci/cli
# Run
lhci autorun --upload.target=temporary-public-storage
# .lighthouserc.json
{
"ci": {
"assert": {
"assertions": {
"categories:performance": ["warn", { "minScore": 0.9 }],
"categories:accessibility": ["error", { "minScore": 1.0 }],
"categories:seo": ["warn", { "minScore": 0.95 }]
}
}
}
}
レビューチェックリスト
- Lighthouse のパフォーマンススコアが 90 以上
- Lighthouse のアクセシビリティスコアが 100
- LCP が 2.5 秒以下 — LCP 画像をプリロードし、その画像に
loading="lazy"を設定しない - CLS が 0.1 以下 — すべての画像に
widthとheightが設定され、レイアウトをずらすアニメーションがない - INP が 200 ミリ秒以下 — メインスレッドで重い同期 JavaScript を実行しない
- 画像を正しい寸法の WebP または AVIF 形式で配信する
- ファーストビューより下にあるすべての画像に
loading="lazy"を設定する - Web フォントで
font-display: swapまたはoptionalを使用する - 重要でない JavaScript を
deferまたはasyncで読み込む - デプロイパイプラインでのリグレッションを検出できるように Lighthouse CI を設定する