Webサイトの表示速度とユーザー体験は、SEOランキングやコンバージョン率に直結する重要な要素です。Googleが提唱するCore Web Vitalsは、Webページのパフォーマンスを「読み込み速度」「インタラクティビティ」「視覚的安定性」の3つの観点から評価するための指標群です。
この記事では、Core Web Vitalsを構成する3つの指標(LCP、INP、CLS)の詳細から、LighthouseやPageSpeed Insightsを使った計測方法、そして具体的なパフォーマンス改善手法まで、Webパフォーマンス最適化の全体像を解説します。
この記事で学べること#
- Core Web Vitalsの3つの指標(LCP、INP、CLS)の意味と評価基準
- LighthouseとPageSpeed Insightsを使ったパフォーマンス計測方法
- 画像最適化、遅延読み込み、Critical CSSなどの具体的な改善手法
- Core Web Vitalsスコアを向上させるベストプラクティス
前提知識と実行環境#
この記事を理解するために必要な前提知識と実行環境は以下の通りです。
| 項目 |
内容 |
| 前提知識 |
HTML/CSS/JavaScriptの基礎、ブラウザの仕組みの基本 |
| 確認環境 |
Google Chrome 131以降、Chrome DevTools、Lighthouse 12 |
| 対象読者 |
SEOやUX向上を目指すフロントエンド開発者、表示速度改善に取り組むエンジニア |
Core Web Vitalsとは#
Core Web Vitalsは、Googleがユーザー体験の品質を測定するために定義した主要なパフォーマンス指標です。2024年3月以降、以下の3つの指標で構成されています。
graph LR
subgraph Core Web Vitals
LCP[LCP<br/>読み込み速度]
INP[INP<br/>インタラクティビティ]
CLS[CLS<br/>視覚的安定性]
end
LCP --> UX[ユーザー体験]
INP --> UX
CLS --> UX
UX --> SEO[SEOランキング]3つの指標の概要#
| 指標 |
正式名称 |
測定対象 |
良好な値 |
| LCP |
Largest Contentful Paint |
ページ内の最大コンテンツが表示されるまでの時間 |
2.5秒以下 |
| INP |
Interaction to Next Paint |
ユーザー操作から視覚的フィードバックまでの時間 |
200ミリ秒以下 |
| CLS |
Cumulative Layout Shift |
ページ読み込み中のレイアウトのずれ |
0.1以下 |
これらの指標は、Googleの検索ランキング要因の一つとして使用されており、Core Web Vitalsのスコア改善はSEO対策としても重要です。
LCP(Largest Contentful Paint)の詳細と改善方法#
LCPは、ビューポート内で最も大きなコンテンツ要素が表示されるまでの時間を測定する指標です。ユーザーが「ページが読み込まれた」と感じるタイミングを表現しています。
LCPの評価基準#
| スコア |
評価 |
ユーザー体験 |
| 2.5秒以下 |
良好(緑) |
ページの読み込みが速いと感じる |
| 2.5秒〜4.0秒 |
改善が必要(オレンジ) |
やや待たされる印象を受ける |
| 4.0秒超 |
不良(赤) |
ページが重いと感じ、離脱の可能性が高まる |
LCPの対象となる要素#
LCPの計測対象となる要素は以下の通りです。
<img>要素
<svg>内の<image>要素
<video>要素のポスター画像
background-imageを持つ要素(CSS)
- テキストノードを含むブロックレベル要素
LCP改善の具体的な手法#
1. サーバーレスポンス時間の短縮#
サーバーからの応答時間(TTFB: Time to First Byte)を短縮することで、LCPを改善できます。
1
2
3
4
5
6
7
8
9
10
11
|
# Nginx でのgzip圧縮設定
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
gzip_min_length 1000;
gzip_comp_level 6;
# キャッシュヘッダーの設定
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
|
2. 画像の最適化#
LCP要素が画像の場合、次世代フォーマットと適切なサイズ指定が重要です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<!-- レスポンシブ画像の実装 -->
<picture>
<source
srcset="hero-480.webp 480w, hero-800.webp 800w, hero-1200.webp 1200w"
sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
type="image/webp">
<source
srcset="hero-480.jpg 480w, hero-800.jpg 800w, hero-1200.jpg 1200w"
sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
type="image/jpeg">
<img
src="hero-800.jpg"
alt="ヒーロー画像"
width="1200"
height="600"
fetchpriority="high">
</picture>
|
3. LCP要素のプリロード#
LCP対象となる画像やフォントを事前に読み込むことで、表示を高速化できます。
1
2
3
4
5
6
7
8
9
10
|
<head>
<!-- LCP画像のプリロード -->
<link rel="preload" as="image" href="/images/hero.webp" type="image/webp">
<!-- Webフォントのプリロード -->
<link rel="preload" as="font" href="/fonts/main.woff2" type="font/woff2" crossorigin>
<!-- 重要なCSSのプリロード -->
<link rel="preload" as="style" href="/css/critical.css">
</head>
|
4. レンダリングブロックリソースの削除#
JavaScriptやCSSがレンダリングをブロックしないように最適化します。
1
2
3
4
5
6
7
8
|
<!-- 非同期でJavaScriptを読み込む -->
<script src="analytics.js" async></script>
<!-- DOMの読み込み後に実行 -->
<script src="non-critical.js" defer></script>
<!-- 条件付きでCSSを読み込む -->
<link rel="stylesheet" href="print.css" media="print">
|
INP(Interaction to Next Paint)の詳細と改善方法#
INPは、2024年3月にFID(First Input Delay)に代わってCore Web Vitalsの指標となりました。ページ全体を通じたユーザーインタラクションの応答性を測定します。
INPとFIDの違い#
| 項目 |
FID(旧指標) |
INP(現行指標) |
| 測定対象 |
最初のインタラクションのみ |
すべてのインタラクション |
| 測定範囲 |
入力遅延のみ |
入力遅延 + 処理時間 + 表示遅延 |
| 代表値 |
最初の1回の値 |
98パーセンタイル値 |
INPの構成要素#
INPは以下の3つのフェーズで構成されます。
sequenceDiagram
participant User as ユーザー
participant Browser as ブラウザ
participant Main as メインスレッド
participant Screen as 画面
User->>Browser: クリック/タップ/キー入力
Note over Browser,Main: 入力遅延<br/>(Input Delay)
Browser->>Main: イベントハンドラ実行開始
Note over Main: 処理時間<br/>(Processing Time)
Main->>Screen: レンダリング開始
Note over Main,Screen: 表示遅延<br/>(Presentation Delay)
Screen->>User: 視覚的フィードバックINPの評価基準#
| スコア |
評価 |
ユーザー体験 |
| 200ミリ秒以下 |
良好(緑) |
即座に反応していると感じる |
| 200ミリ秒〜500ミリ秒 |
改善が必要(オレンジ) |
やや遅れを感じる |
| 500ミリ秒超 |
不良(赤) |
操作が効いていないと感じる |
INP改善の具体的な手法#
1. 長時間タスクの分割#
メインスレッドをブロックする長時間タスクを分割して、ユーザー入力に素早く応答できるようにします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
// 悪い例: 長時間タスクがメインスレッドをブロック
function processLargeData(items) {
items.forEach(item => {
// 重い処理
heavyComputation(item);
});
}
// 良い例: タスクを分割して処理
async function processLargeDataOptimized(items) {
const CHUNK_SIZE = 100;
for (let i = 0; i < items.length; i += CHUNK_SIZE) {
const chunk = items.slice(i, i + CHUNK_SIZE);
// 各チャンクの処理
chunk.forEach(item => heavyComputation(item));
// ブラウザに制御を返す
await yieldToMain();
}
}
// メインスレッドに制御を返すユーティリティ
function yieldToMain() {
return new Promise(resolve => {
setTimeout(resolve, 0);
});
}
|
2. scheduler.yield()の活用#
ブラウザのscheduler.yield()APIを使用して、より効率的にメインスレッドに制御を返すことができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
async function processWithYield(items) {
for (const item of items) {
// 処理を実行
processItem(item);
// scheduler.yield()が利用可能な場合は使用
if ('scheduler' in window && 'yield' in scheduler) {
await scheduler.yield();
} else {
// フォールバック
await new Promise(resolve => setTimeout(resolve, 0));
}
}
}
|
3. イベントハンドラの最適化#
不要な処理を削減し、イベントハンドラを軽量に保ちます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// 悪い例: 重い処理をクリックハンドラ内で実行
button.addEventListener('click', () => {
// 即座に視覚的フィードバックを提供しない
const result = expensiveCalculation();
updateUI(result);
});
// 良い例: 視覚的フィードバックを先に、重い処理は後で
button.addEventListener('click', () => {
// 即座に視覚的フィードバックを提供
button.classList.add('loading');
button.disabled = true;
// 重い処理は次のフレームで実行
requestAnimationFrame(() => {
requestAnimationFrame(async () => {
const result = await expensiveCalculation();
updateUI(result);
button.classList.remove('loading');
button.disabled = false;
});
});
});
|
4. Web Workerの活用#
CPU負荷の高い処理をメインスレッドから分離します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// main.js
const worker = new Worker('worker.js');
button.addEventListener('click', () => {
// 視覚的フィードバックを即座に表示
showLoadingIndicator();
// 重い処理をWeb Workerに委譲
worker.postMessage({ type: 'PROCESS_DATA', data: largeDataSet });
});
worker.addEventListener('message', (event) => {
const { result } = event.data;
updateUI(result);
hideLoadingIndicator();
});
|
1
2
3
4
5
6
7
8
9
10
|
// worker.js
self.addEventListener('message', (event) => {
const { type, data } = event.data;
if (type === 'PROCESS_DATA') {
// メインスレッドに影響を与えずに重い処理を実行
const result = expensiveComputation(data);
self.postMessage({ result });
}
});
|
CLS(Cumulative Layout Shift)の詳細と改善方法#
CLSは、ページ読み込み中およびページのライフサイクル全体を通じて発生する予期しないレイアウトシフトを測定する指標です。
CLSの計算方法#
CLSは、影響を受ける領域(Impact Fraction)と移動距離(Distance Fraction)の積で計算されます。
レイアウトシフトスコア = Impact Fraction × Distance Fraction
graph TD
subgraph レイアウトシフトの発生
A[要素が移動] --> B[Impact Fraction<br/>ビューポートの何%が影響を受けたか]
A --> C[Distance Fraction<br/>要素が何%移動したか]
B --> D[CLS Score = Impact × Distance]
C --> D
endCLSの評価基準#
| スコア |
評価 |
ユーザー体験 |
| 0.1以下 |
良好(緑) |
レイアウトが安定している |
| 0.1〜0.25 |
改善が必要(オレンジ) |
時々ずれを感じる |
| 0.25超 |
不良(赤) |
頻繁にレイアウトがずれる |
CLS改善の具体的な手法#
1. 画像とメディアのサイズ指定#
画像や動画要素には必ずwidthとheight属性を指定し、アスペクト比を維持します。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!-- 悪い例: サイズ指定なし -->
<img src="photo.jpg" alt="写真">
<!-- 良い例: サイズを明示的に指定 -->
<img src="photo.jpg" alt="写真" width="800" height="600">
<!-- CSSでアスペクト比を維持 -->
<style>
img {
max-width: 100%;
height: auto;
}
</style>
|
2. aspect-ratioプロパティの活用#
CSSのaspect-ratioプロパティを使用して、コンテナのアスペクト比を事前に確保します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/* 動画コンテナ(16:9) */
.video-container {
aspect-ratio: 16 / 9;
width: 100%;
background-color: #f0f0f0;
}
/* 画像プレースホルダー(4:3) */
.image-placeholder {
aspect-ratio: 4 / 3;
width: 100%;
background-color: #e0e0e0;
}
/* 正方形のサムネイル */
.thumbnail {
aspect-ratio: 1 / 1;
width: 100px;
object-fit: cover;
}
|
3. 広告・埋め込みコンテンツのスペース確保#
動的に読み込まれる広告やiframeのスペースを事前に確保します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<!-- 広告スロット用のコンテナ -->
<div class="ad-slot" style="min-height: 250px; min-width: 300px;">
<!-- 広告が読み込まれる -->
</div>
<style>
.ad-slot {
/* フォールバック表示 */
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
}
.ad-slot:empty::before {
content: "広告";
color: #999;
}
</style>
|
4. Webフォントによるレイアウトシフトの防止#
Webフォントの読み込みによるテキストのちらつきを防止します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/* フォントのプリロード */
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap; /* または optional */
/* size-adjust でメトリクスを調整 */
size-adjust: 100%;
ascent-override: 90%;
descent-override: 20%;
}
/* フォールバックフォントとのサイズ調整 */
body {
font-family: 'CustomFont', -apple-system, BlinkMacSystemFont, sans-serif;
}
|
1
2
3
4
5
6
7
8
9
|
<head>
<!-- フォントのプリロード -->
<link
rel="preload"
as="font"
href="/fonts/custom.woff2"
type="font/woff2"
crossorigin>
</head>
|
5. 動的コンテンツの挿入位置の工夫#
既存コンテンツの上に新しい要素を挿入しないようにします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 悪い例: 既存コンテンツの上に挿入
function addNotification(message) {
const notification = document.createElement('div');
notification.textContent = message;
document.body.insertBefore(notification, document.body.firstChild);
}
// 良い例: 固定位置に表示
function addNotificationOptimized(message) {
const notification = document.createElement('div');
notification.className = 'notification';
notification.textContent = message;
document.body.appendChild(notification);
}
|
1
2
3
4
5
6
7
|
.notification {
position: fixed;
top: 16px;
right: 16px;
z-index: 1000;
/* レイアウトに影響を与えない */
}
|
Lighthouseによるパフォーマンス計測#
Lighthouseは、Googleが提供するオープンソースの自動化ツールで、Webページの品質を測定できます。
Lighthouseの実行方法#
- Chrome DevToolsを開く(F12またはCmd/Ctrl + Shift + I)
- 「Lighthouse」タブを選択
- 計測するカテゴリを選択(Performance、Accessibility等)
- 「Analyze page load」をクリック
コマンドラインから実行#
1
2
3
4
5
6
7
8
9
10
11
|
# Lighthouse CLIのインストール
npm install -g lighthouse
# 基本的な実行
lighthouse https://example.com --output html --output-path report.html
# モバイルエミュレーションで実行
lighthouse https://example.com --preset=perf --form-factor=mobile
# デスクトップモードで実行
lighthouse https://example.com --preset=desktop
|
Lighthouseのパフォーマンススコア構成(v10以降)#
| 指標 |
重み |
説明 |
| First Contentful Paint(FCP) |
10% |
最初のコンテンツが表示されるまでの時間 |
| Speed Index |
10% |
コンテンツが視覚的に表示される速度 |
| Largest Contentful Paint(LCP) |
25% |
最大のコンテンツが表示されるまでの時間 |
| Total Blocking Time(TBT) |
30% |
メインスレッドがブロックされた合計時間 |
| Cumulative Layout Shift(CLS) |
25% |
レイアウトシフトの累積スコア |
Lighthouseレポートの読み方#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// Lighthouseの出力例(JSON形式)
{
"categories": {
"performance": {
"score": 0.85, // 85点
"auditRefs": [
{ "id": "largest-contentful-paint", "weight": 25 },
{ "id": "total-blocking-time", "weight": 30 },
{ "id": "cumulative-layout-shift", "weight": 25 }
]
}
},
"audits": {
"largest-contentful-paint": {
"score": 0.92,
"numericValue": 1850, // 1.85秒
"displayValue": "1.9 s"
}
}
}
|
PageSpeed Insightsによるパフォーマンス計測#
PageSpeed Insightsは、ラボデータ(Lighthouse)とフィールドデータ(CrUX)の両方を提供するツールです。
ラボデータとフィールドデータの違い#
| 項目 |
ラボデータ |
フィールドデータ |
| データソース |
Lighthouse(シミュレーション) |
Chrome User Experience Report |
| 測定環境 |
固定された条件 |
実際のユーザー環境 |
| 用途 |
開発・デバッグ |
実際のユーザー体験の把握 |
| 更新頻度 |
リアルタイム |
28日間のローリングデータ |
PageSpeed Insights APIの活用#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// PageSpeed Insights APIの呼び出し例
async function getPageSpeedInsights(url) {
const apiKey = 'YOUR_API_KEY';
const apiUrl = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${encodeURIComponent(url)}&key=${apiKey}&category=performance&strategy=mobile`;
const response = await fetch(apiUrl);
const data = await response.json();
// Core Web Vitalsの抽出
const metrics = {
lcp: data.loadingExperience?.metrics?.LARGEST_CONTENTFUL_PAINT_MS,
inp: data.loadingExperience?.metrics?.INTERACTION_TO_NEXT_PAINT,
cls: data.loadingExperience?.metrics?.CUMULATIVE_LAYOUT_SHIFT_SCORE
};
return metrics;
}
|
Critical CSSによる初期表示の高速化#
Critical CSSとは、ファーストビューの表示に必要な最小限のCSSをインライン化する手法です。
Critical CSSの抽出と適用#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Critical CSSをインライン化 -->
<style>
/* ファーストビューに必要な最小限のCSS */
body { margin: 0; font-family: sans-serif; }
.header { background: #333; color: white; padding: 1rem; }
.hero { height: 60vh; display: flex; align-items: center; }
.hero-title { font-size: 2.5rem; margin: 0; }
</style>
<!-- 残りのCSSは非同期で読み込み -->
<link rel="preload" href="/css/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/main.css"></noscript>
</head>
<body>
<header class="header">サイトヘッダー</header>
<section class="hero">
<h1 class="hero-title">メインタイトル</h1>
</section>
</body>
</html>
|
Critical CSSの自動抽出#
Criticalライブラリを使用して、Critical CSSを自動的に抽出できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// critical.config.js
const critical = require('critical');
critical.generate({
base: 'dist/',
src: 'index.html',
target: {
html: 'index-critical.html',
css: 'critical.css'
},
width: 1300,
height: 900,
inline: true,
extract: true
});
|
遅延読み込み(Lazy Loading)の実装#
ビューポート外のコンテンツを遅延読み込みすることで、初期読み込み時間を短縮できます。
ネイティブLazy Loading#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<!-- 画像の遅延読み込み -->
<img
src="image.jpg"
alt="説明"
loading="lazy"
width="800"
height="600">
<!-- iframeの遅延読み込み -->
<iframe
src="https://www.youtube.com/embed/VIDEO_ID"
loading="lazy"
width="560"
height="315">
</iframe>
|
Intersection Observerを使った高度な遅延読み込み#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
// Intersection Observerによる遅延読み込み
class LazyLoader {
constructor(options = {}) {
this.options = {
root: null,
rootMargin: '50px 0px',
threshold: 0.01,
...options
};
this.observer = new IntersectionObserver(
this.handleIntersection.bind(this),
this.options
);
}
observe(elements) {
elements.forEach(el => this.observer.observe(el));
}
handleIntersection(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.loadElement(entry.target);
this.observer.unobserve(entry.target);
}
});
}
loadElement(element) {
const src = element.dataset.src;
const srcset = element.dataset.srcset;
if (src) element.src = src;
if (srcset) element.srcset = srcset;
element.classList.add('loaded');
}
}
// 使用例
const lazyLoader = new LazyLoader();
const lazyImages = document.querySelectorAll('img[data-src]');
lazyLoader.observe(lazyImages);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<!-- 遅延読み込み用のマークアップ -->
<img
data-src="large-image.jpg"
data-srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
alt="遅延読み込み画像"
width="1200"
height="800"
class="lazy">
<style>
.lazy {
opacity: 0;
transition: opacity 0.3s;
}
.lazy.loaded {
opacity: 1;
}
</style>
|
web-vitalsライブラリによる計測#
Googleが提供するweb-vitalsライブラリを使用して、実際のユーザー環境でCore Web Vitalsを計測できます。
web-vitalsの導入と基本的な使用方法#
1
2
|
# インストール
npm install web-vitals
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
import { onCLS, onINP, onLCP, onFCP, onTTFB } from 'web-vitals';
// 計測結果をアナリティクスに送信
function sendToAnalytics(metric) {
const body = JSON.stringify({
name: metric.name,
value: metric.value,
rating: metric.rating, // 'good', 'needs-improvement', 'poor'
delta: metric.delta,
id: metric.id,
navigationType: metric.navigationType
});
// Beacon APIで送信(ページ離脱時も確実に送信)
if (navigator.sendBeacon) {
navigator.sendBeacon('/analytics', body);
} else {
fetch('/analytics', {
body,
method: 'POST',
keepalive: true
});
}
}
// 各指標を監視
onCLS(sendToAnalytics);
onINP(sendToAnalytics);
onLCP(sendToAnalytics);
onFCP(sendToAnalytics);
onTTFB(sendToAnalytics);
|
アトリビューション情報の取得#
より詳細なデバッグ情報を取得するには、アトリビューションビルドを使用します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import { onLCP, onINP, onCLS } from 'web-vitals/attribution';
onLCP((metric) => {
console.log('LCP:', metric.value);
console.log('LCP要素:', metric.attribution.element);
console.log('リソースURL:', metric.attribution.url);
console.log('TTFB:', metric.attribution.timeToFirstByte);
});
onINP((metric) => {
console.log('INP:', metric.value);
console.log('インタラクション対象:', metric.attribution.interactionTarget);
console.log('インタラクションタイプ:', metric.attribution.interactionType);
console.log('入力遅延:', metric.attribution.inputDelay);
console.log('処理時間:', metric.attribution.processingDuration);
console.log('表示遅延:', metric.attribution.presentationDelay);
});
onCLS((metric) => {
console.log('CLS:', metric.value);
console.log('最大シフト要素:', metric.attribution.largestShiftTarget);
console.log('最大シフト時間:', metric.attribution.largestShiftTime);
});
|
パフォーマンス改善のベストプラクティス#
チェックリスト形式のまとめ#
LCP改善チェックリスト#
INP改善チェックリスト#
CLS改善チェックリスト#
パフォーマンス監視の継続的な実施#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// パフォーマンスバジェットの設定例
const performanceBudget = {
lcp: 2500, // 2.5秒
inp: 200, // 200ms
cls: 0.1, // 0.1
fcp: 1800, // 1.8秒
ttfb: 600 // 600ms
};
// バジェット超過時のアラート
function checkBudget(metric) {
const budget = performanceBudget[metric.name.toLowerCase()];
if (budget && metric.value > budget) {
console.warn(`パフォーマンスバジェット超過: ${metric.name} = ${metric.value} (上限: ${budget})`);
// Slackやメールへの通知
notifyTeam(metric);
}
}
|
まとめ#
Core Web Vitalsは、Webパフォーマンスを体系的に評価・改善するための重要な指標です。本記事で解説した内容を実践することで、ユーザー体験とSEOの両面で成果を上げることができます。
パフォーマンス最適化は一度行えば終わりではなく、継続的な計測と改善が重要です。LighthouseやPageSpeed Insights、web-vitalsライブラリを活用して定期的に計測を行い、問題が発生した際に迅速に対応できる体制を整えましょう。
参考リンク#