LCP の最適化: 画像のプリロード、クリティカル CSS および SSR
Il 最大のコンテンツフル ペイント (LCP) 経過する時間を測る ページの読み込みから最大の要素がページに表示される瞬間まで ビューポートがレンダリングされます。 Google は 2.5 秒未満の LCP を「良好」とみなします。 2.5秒から4秒の間は「改善の余地がある」、4秒を超えると「悪い」。 3つのうちの1つです 検索ランキングに直接影響を与えるコア ウェブ バイタル。
LCP を最適化するには、次のことを理解する必要があります。 クリティカルパス: シーケンス 要素をレンダリングする前にブラウザが完了する必要がある操作 LCP。クリティカル パス上に不要なリソースがあると、LCP が遅延します。 4つの戦略 より大きな影響 — 画像のプリロード、重要なインライン CSS、最適化 フォントとサーバーサイドレンダリングの削減 - ほとんどの場合、LCP を 500ms ~ 2 秒削減します 実際の事例の一部。
何を学ぶか
- ブラウザが LCP 要素を検出してロードする方法: クリティカル パス
- fetchpriority="high": どの画像が優先されるかをブラウザに伝えます
- rel="preload": パーサーがリソースを検出する前にリソースをプリロードします。
- クリティカル CSS インライン: スタイルシートのレンダリング ブロックを排除します。
- font-display: swap および LCP を遅らせる FOIT を回避するためのオプション
- サーバーサイド レンダリング: LCP のウォーターフォール JS を削除する
- WebPageTest と PerformanceObserver で実際の影響を測定する
LCP のクリティカル パス
最適化する前に、特定のケースで LCP をブロックしているものを理解する必要があります。 ブラウザは次の手順に従って LCP 要素をレンダリングします。
// PerformanceObserver: misura il tuo LCP reale
const observer = new PerformanceObserver((list) => {
// L'ultimo entry e il piu aggiornato
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP Element:', lastEntry.element?.tagName);
console.log('LCP Time:', lastEntry.startTime.toFixed(0), 'ms');
console.log('LCP URL:', lastEntry.url); // se e un'immagine
// Breakdown del tempo LCP
if (lastEntry.element) {
const el = lastEntry.element;
const rect = el.getBoundingClientRect();
console.log('Element size:', rect.width * rect.height, 'px^2');
}
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
// Quali elementi vengono considerati per l'LCP?
// - img elements
// - image elements dentro svg
// - video elements (usa il poster)
// - background-image (solo via CSS)
// - block-level elements con testo (h1, p, div con testo visibile)
// L'elemento piu grande nel viewport al momento del paint
// Come trovare l'elemento LCP in DevTools:
// 1. Apri Chrome DevTools > Performance
// 2. Registra un caricamento
// 3. Cerca "LCP" nella timeline
// 4. Clicca sull'entry: mostra quale elemento
fetchpriority="high": 明示的なブラウザ優先度
ブラウザは内部優先システムを使用して、どのリソースをロードするかを決定します。
前に。デフォルトでは、画像の優先度は低または中です。属性
fetchpriority="high" この画像が LCP であることをブラウザに伝えます
要素であり、最初にロードする必要があります。
クリティカル CSS インライン: レンダリングのブロックを排除する
外部スタイルシートは、ダウンロードされて解析されるまでレンダリングをブロックします。 ネットワークが遅いかサーバーが遅い場合、LCP は 500ms-2 秒しか遅延しません。 CSS ファイルの場合。解決策: 重要な CSS をインライン化する 直接 HTML (スクロールせずに見える部分にコンテンツを表示するために必要な CSS) e 残りを非同期でロードします。
// Tool per estrarre automaticamente il Critical CSS
// criticalcss (npm) oppure Vite Critical CSS plugin
// Configurazione Vite con vite-plugin-critical
// vite.config.ts
import { defineConfig } from 'vite';
import critical from 'vite-plugin-critical';
export default defineConfig({
plugins: [
critical({
criticalUrl: 'http://localhost:4173',
criticalBase: 'dist/',
criticalPages: [
{ uri: '/', template: 'index' },
{ uri: '/blog', template: 'blog' },
],
criticalConfig: {
inline: true,
dimensions: [
{ width: 375, height: 812 }, // iPhone
{ width: 1440, height: 900 }, // Desktop
],
},
}),
],
});
フォントの最適化: クリティカル パス上の FOIT を排除する
Web フォントは、LCP 要素テキストのレンダリングをブロックすることがよくあります。フォントがそうでない場合は、
まだロードされているため、ブラウザは (FOIT - 不可視テキストのフラッシュ) を待機します。
テキストをレンダリングします。 font-display: swap 最初にフォールバックを表示する
その後、置き換えますが、CLS を作成します。 font-display: optional そして選択
LCP に適しています: フォントがまだキャッシュされていない場合はフォールバックを使用します。
/* Font loading ottimizzato per LCP */
/* 1. Preconnect al CDN del font (risparmia ~100ms di DNS lookup) */
/* Nel :
*/
/* 2. Preload del font critico (quello usato dall'LCP element) */
/* Nel :
*/
/* 3. font-display strategy */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-latin-400.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: optional;
/* optional: usa il font solo se gia in cache.
Al primo caricamento usa system font (zero FOIT, zero CLS).
Dal secondo caricamento usa il web font. */
unicode-range: U+0000-00FF; /* Solo Latin: riduce dimensione */
}
/* Per testi LCP critici: usa fallback con metriche simili */
/* Riduci CLS da font swap usando size-adjust */
@font-face {
font-family: 'Inter-Fallback';
src: local('Arial'); /* Font di sistema come fallback */
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
size-adjust: 107%;
/* Metriche calibrate per ridurre il layout shift */
}
.lcp-heading {
font-family: 'Inter', 'Inter-Fallback', system-ui;
}
サーバーサイド レンダリング: JavaScript ウォーターフォールの排除
クライアント側レンダリングを使用するシングル ページ アプリケーション (SPA) には問題があります LCP の構造: ブラウザは HTML をダウンロードし、JavaScript を実行する必要があります。 データにリクエストを行ってから、コンテンツをレンダリングします。この「滝」は、 LCP に 1 ~ 3 秒を追加します。サーバーサイド レンダリング (SSR) がこれを解決します すでにレンダリングされた HTML をクライアントに送信します。
// Impatto SSR sull'LCP: misurazioni reali
// SPA senza SSR: waterfall tipico
// 0ms - Browser riceve HTML (vuoto, solo )
// 200ms - Scarica bundle JavaScript (150KB gzipped)
// 400ms - Esegue JavaScript, monta il framework
// 600ms - Prima render: scheletro UI (loading spinner)
// 800ms - API request per i dati
// 1200ms - Risposta API
// 1300ms - Render con dati: LCP event
// LCP = ~1300ms (buono ma potrebbe essere meglio)
// Con SSR: nessun waterfall
// 0ms - Browser invia request
// 150ms - Server renderizza HTML completo con dati
// 350ms - Browser riceve HTML gia renderizzato con l'LCP element visibile
// 350ms - LCP event: l'elemento e gia nella pagina!
// LCP = ~350ms (eccellente)
// Angular Universal (SSR) - esempio di configurazione
// angular.json: abilita SSR
// "server": { "builder": "@angular-devkit/build-angular:application" }
// app.config.server.ts:
import { ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
export const serverConfig: ApplicationConfig = {
providers: [
provideServerRendering(),
],
};
// Next.js: LCP ottimale con SSR e Image component
// Ogni pagina e server-rendered by default in App Router
// Il componente Image gestisce automaticamente:
// - fetchpriority="high" per above-fold images
// - preload link nel head
// - srcset per responsive images
// - dimensioni esplicite per evitare CLS
影響の測定: 前後
// Misura il tuo LCP prima di ottimizzare
// e dopo per verificare il miglioramento
// web-vitals.js: libreria Google per misurare CWV
import { onLCP, onFID, onCLS } from 'web-vitals';
function sendToAnalytics(metric) {
// Invia a Google Analytics o sistema custom
gtag('event', metric.name, {
value: Math.round(metric.value),
metric_id: metric.id,
metric_value: metric.value,
metric_delta: metric.delta,
metric_rating: metric.rating, // 'good' | 'needs-improvement' | 'poor'
});
}
onLCP(sendToAnalytics);
// WebPageTest: test sintetico con waterfall dettagliato
// https://www.webpagetest.org
// Parametri raccomandati:
// - Location: EC2 Frankfurt (per utenti EU)
// - Connection: 4G (LTE) - 9 Mbps down, 9 Mbps up, 170ms RTT
// - Repeat Views: si (testa cache)
// - Video capture: si (vedi frame-by-frame quando appare l'LCP)
// Risultati da cercare nel waterfall:
// - Quante risorse bloccano il rendering? (Resources in Critical Chain)
// - Quando viene scoperta l'immagine LCP? (piu presto = meglio)
// - Quanto dura il "Render-Blocking" bar? (dovrebb essere < 200ms)
LCP 最適化チェックリスト
- DevTools Performance または WebPageTest を使用して LCP 要素を特定する
- LCP 要素から fetchpriority="high" を追加し、loading="lazy" を削除します。
- 画像の場合: AVIF/WebP、レスポンシブ srcset、明示的なサイズを使用
- クリティカル CSS をスクロールせずに見える範囲にインライン化し、残りを非同期でロードします
- LCP要素で使用されるフォントをプリロードします。
- SSR を使用する場合: LCP 要素が最初の HTML にあることを確認してください。
- 本番環境で CrUX または web-vitals.js を使用して LCP P75 を測定する
結論
LCP の最適化は基本的に時間を短縮するための演習です クリティカル パス上: レンダリング前にブラウザがダウンロードする必要があるすべてのリソース LCP 要素は改善の機会です。 fetchpriority を使用する場合、重要な CSS インラインおよび SSR を使用すると、一般的なモバイル接続で 1 秒未満の LCP を達成できます。







