mcpField
C
core-web-vitals

core-web-vitals

github.com/addyosmani開発3.0k32.4k 回インストール9 週間前に更新
リポジトリ

core-web-vitals について

Web開発者向けのCore Web Vitals最適化スキルです。実ユーザーデータで影響度を判断し、ブラウザーのパフォーマンストレースでLCP、INP、CLSの問題を診断します。

主な機能

  1. 01ページ単位のCrUXデータを優先
  2. 02トレースによる指標問題の診断
  3. 03LCP、INP、CLSを対象
  4. 04フィールドデータとラボ結果の区別
  5. 05指標別の最適化ガイダンス

活用シーン

  1. 01実ユーザー指標が低い原因の特定
  2. 02ページ操作の応答遅延の調査
  3. 03トレースによるレイアウトシフトの診断

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/addyosmani/web-quality-skills --skill core-web-vitals

インストール後、Claude Code で/core-web-vitalsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
CLS.md
INP.md
LCP.md

詳細

Core Web Vitals の最適化

フィールドデータでユーザーへの影響を特定し、ブラウザのトレースで原因を診断して、3 つの Core Web Vitals を重点的に最適化します。

最適化の前に測定する

実行可能な URL がある場合は、パフォーマンス測定のワークフローを確認してください。次の順序で進めることを推奨します。

  1. ページレベルの CrUX p75 データを確認します。ページデータがない場合は、オリジンのデータを代替として使用することを明記してください。
  2. 条件を明記したうえで、ブラウザーのパフォーマンストレースを記録します。Chrome DevTools MCP では、トレースの概要に、観測されたラボ指標とともに CrUX を含めることができます。
  3. 問題のある指標に関連するインサイトだけを分析し、次に該当するコードとリソースを調べます。
  4. 修正後、同等のラボ測定を再実行します。フィールドデータがすぐに改善すると主張しないでください。CrUX とファーストパーティ RUM には、新たなユーザー訪問が必要です。

ソースコードしかない場合は、考えられる原因を特定します。ただし、実行時の証拠がない限り、LCP、INP、CLS に問題があると主張しないでください。

3 つの指標

指標測定対象良好要改善不良
LCP読み込み≤ 2.5s2.5s – 4s> 4s
INP応答性≤ 200ms200ms – 500ms> 500ms
CLS視覚的な安定性≤ 0.10.1 – 0.25> 0.25

Google は75 パーセンタイルで測定します。ページ訪問の 75% が「良好」のしきい値を満たす必要があります。


LCP:Largest Contentful Paint

LCP は、表示領域内で最も大きなコンテンツ要素が描画されるまでの時間を測定します。通常、対象となるのは次の要素です。

  • ヒーロー画像または動画
  • 大きなテキストブロック
  • 背景画像
  • <svg> 要素
LCP でよくある問題

1. サーバー応答が遅い(TTFB > 800ms)

Fix: CDN, caching, optimized backend, edge rendering

2. 描画をブロックするリソース


<link rel="stylesheet" href="/all-styles.css">


<style>/* Critical above-fold CSS */</style>
<link rel="preload" href="/styles.css" as="style" 
      onload="this.onload=null;this.rel='stylesheet'">

3. リソースの読み込み時間が長い


<div class="hero"></div>


<link rel="preload" href="/hero.webp" as="image" fetchpriority="high">
<img src="/hero.webp" alt="Hero" fetchpriority="high">

fetchpriority="high" を指定した、検出しやすい <img> を優先してください。リソースが遅れて検出されることをトレースが示す場合に限り、プリロードを追加してください。重複または推測的なプリロードは、帯域幅を取り合う可能性があります。

4. クライアントサイドレンダリングによる遅延

// ❌ Content loads after JavaScript
useEffect(() => {
  fetch('/api/hero-text').then(r => r.json()).then(setHeroText);
}, []);

// ✅ Server-side or static rendering
// Use SSR, SSG, or streaming to send HTML with content
export async function getServerSideProps() {
  const heroText = await fetchHeroText();
  return { props: { heroText } };
}

5. Speculation Rules API でページ遷移を瞬時にする

同一オリジン内の遷移を予測できるサイトでは、次に表示される可能性が高いページを事前レンダリングすることで、その後のページ遷移を大幅に高速化できます。これは測定に基づくページ遷移の最適化として扱い、現在のページの LCP を改善する代わりに用いないでください。

<script type="speculationrules">
{
  "prerender": [{
    "where": { "href_matches": "/*" },
    "eagerness": "moderate"
  }]
}
</script>

現在の Chrome の動作は、選択の指針となるほど具体的です。

eagernessトリガー
conservativeポインターまたはタッチの押下
moderateデスクトップ:200ms のホバー、またはそれより早いポインターの押下。モバイル:ビューポートのヒューリスティック
eagerChrome 143 以降:デスクトップでは 10ms のホバー。モバイルではアンカーがビューポートに入ってから 50ms 後
immediateルールが検出されるとすぐ

まずは慎重な設定から始め、ルールを拡張する前に、予測の的中率、転送バイト数、サーバー負荷、ページ遷移の改善を測定してください。タイミングに依存する動作をハードコードする前に、Chrome が管理する eagerness のドキュメントを再確認してください。

注意点:

  • 帯域幅/CPU のコスト。 プリレンダリング 1 回につき、ほぼページ全体の読み込みに相当します。where の範囲は慎重に設定し(href_matches パターンを使い、ログアウト/チェックアウトを除外)、小規模なサイト以外では immediate を避けてください。
  • 副作用が早く発生します。 分析、広告、読み込み時に実行されるコードは、ユーザーがページに遷移したときではなく、プリレンダリングの開始時に実行されます。副作用は、prerenderingchange イベントまたは document.prerendering を使って制御してください。
  • Chromium のみ。 Safari と Firefox はこのスクリプトを無視します。プログレッシブエンハンスメントとして使用し、機能の低下を引き起こさないようにしてください。
LCP 最適化チェックリスト
- [ ] TTFB < 800ms (use CDN, edge caching)
- [ ] LCP resource is discoverable in initial HTML and prioritized; preload only if the trace shows late discovery
- [ ] LCP image optimized (WebP/AVIF, correct size)
- [ ] Critical CSS inlined (< 14KB)
- [ ] No render-blocking JavaScript in <head>
- [ ] Fonts don't block text rendering (font-display: swap)
- [ ] LCP element in initial HTML (not JS-rendered)
- [ ] Speculation Rules added for likely-next navigations (moderate eagerness)
LCP 要素の特定

このスニペットは、現在のページセッションを診断します。フィールドデータではありません。

// Find your LCP element
new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];
  console.log('LCP element:', lastEntry.element);
  console.log('LCP time:', lastEntry.startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });

INP:次の描画までのインタラクション

INP は、訪問中のクリック、タップ、キー入力に対する応答性を測定します。入力遅延、処理時間、表示遅延を個別に診断してください。インタラクションが遅い場合、ハンドラーの実行前にメインスレッドが競合している、アプリケーションの処理に時間がかかっている、または処理後の描画が遅れている可能性があります。

フィールド INP が低い場合、またはトレースで遅いインタラクションが特定された場合は、INP リファレンスを参照し、トレースの解釈、処理を譲るパターン、サードパーティや描画に起因する問題、単一セッションのオブザーバー、ファーストパーティのアトリビューションについて確認してください。


CLS:累積レイアウトシフト

CLS は、ページの訪問中に発生する予期しないレイアウトシフトを測定します。フィールドのアトリビューションまたはトレースを使って、シフトしたノードとそのトリガーを特定してください。見た目に影響を受けた要素がシフトの原因だと決めつけないでください。

フィールド CLS が低い場合、またはトレースでシフトが報告された場合は、CLS リファレンスを参照し、スペースを確保するパターン、動的コンテンツ、フォントやアニメーションの修正、デバッグ用オブザーバー、検証チェックリストについて確認してください。


測定ソース

ソース用途
ブラウザーのパフォーマンストレース(Chrome DevTools MCP:performance_start_trace)1 回の読み込みまたはインタラクションを観察し、対象を絞ったインサイトを診断します。利用可能な場合は、含まれている CrUX コンテキストを使用します
CrUX または Search Consolep75 における実ユーザーの集計結果を基に優先順位を決めます
Lighthouse CLI または PageSpeed InsightsDevTools ツールを利用できない場合の、制御されたラボ測定の代替手段です
ファーストパーティ RUM現在の本番環境におけるエクスペリエンスを、ルート、デバイス、リリース、アトリビューションごとに分類します
生の PerformanceObserverデバッグ中に 1 ページのセッションを調べます

パフォーマンスの測定に Chrome DevTools MCP の lighthouse_audit を使わないでください。この機能は、パフォーマンス以外の Lighthouse カテゴリーを対象としています。また、単一のラボ測定値をフィールド p75 と同等のサンプルであるかのように直接比較しないでください。

本番環境の測定を追加または確認する場合は、ファーストパーティ RUM リファレンスを参照してください。生のブラウザー API だけでは、すべての Core Web Vitals のライフサイクルと報告ルールが実装されないため、web-vitals ライブラリの使用を推奨します。


フレームワーク別のクイック修正

Next.js
// LCP: Use next/image with priority
import Image from 'next/image';
<Image src="/hero.jpg" priority fill alt="Hero" />

// INP: Use dynamic imports
const HeavyComponent = dynamic(() => import('./Heavy'), { ssr: false });

// CLS: Image component handles dimensions automatically
React
// LCP: Preload in head
<link rel="preload" href="/hero.jpg" as="image" fetchpriority="high" />

// INP: Memoize and useTransition
const [isPending, startTransition] = useTransition();
startTransition(() => setExpensiveState(newValue));

// CLS: Always specify dimensions in img tags
Vue/Nuxt

<NuxtImg src="/hero.jpg" preload loading="eager" />


<component :is="() => import('./Heavy.vue')" />


<img :style="{ aspectRatio: '16/9' }" />

リファレンス

コメント