Optymalizacja LCP: wstępne ładowanie obrazu, krytyczne CSS i SSR
Il Największa zawartość farby (LCP) zmierzyć upływający czas od wczytania strony do momentu, w którym w pliku widoczny jest największy element rzutnia jest renderowana. Google uważa LCP poniżej 2,5 sekundy za „dobry”, od 2,5 do 4 sekund „do poprawy”, powyżej 4 sekund „słabo”. To jeden z trzech Podstawowe wskaźniki internetowe, które bezpośrednio wpływają na rankingi wyszukiwania.
Optymalizacja LCP wymaga zrozumienia ścieżka krytyczna: sekwencja operacji, które przeglądarka musi wykonać, zanim będzie mogła wyrenderować element LCP. Wszelkie niepotrzebne zasoby na ścieżce krytycznej opóźniają LCP. Cztery strategie większy wpływ — wstępne ładowanie obrazu, krytyczny wbudowany CSS, optymalizacja czcionek i renderowania po stronie serwera — w większości przypadków zmniejsz LCP o 500 ms–2 sekundy część prawdziwych przypadków.
Czego się nauczysz
- Jak przeglądarka odkrywa i ładuje element LCP: ścieżka krytyczna
- fetchpriority="high": powiedz przeglądarce, który obraz jest priorytetowy
- rel="preload": Wstępnie załaduj zasoby, zanim parser je wykryje
- Krytyczny wbudowany CSS: wyeliminuj blokowanie renderowania arkuszy stylów
- wyświetlanie czcionek: zamień i opcjonalnie, aby uniknąć FOIT, który opóźnia LCP
- Renderowanie po stronie serwera: Wyeliminuj wodospad JS dla LCP
- Zmierz rzeczywisty wpływ za pomocą WebPageTest i PerformanceObserver
Ścieżka krytyczna dla LCP
Przed optymalizacją musisz zrozumieć, co blokuje LCP w Twoim konkretnym przypadku. Przeglądarka wykonuje następujące kroki, aby wyrenderować element 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": Jawny priorytet przeglądarki
Przeglądarka korzysta z wewnętrznego systemu priorytetów, aby zdecydować, które zasoby załadować
wcześniej. Domyślnie obrazy mają niski lub średni priorytet. Atrybut
fetchpriority="high" informuje przeglądarkę, że ten obraz to LCP
element i musi zostać załadowany jako pierwszy.
Krytyczny CSS Inline: Wyeliminuj blokowanie renderowania
Zewnętrzne arkusze stylów blokują renderowanie do czasu pobrania i przeanalizowania. Wolna sieć lub wolny serwer może opóźnić LCP jedynie o 500 ms–2 sekundy dla pliku CSS. Rozwiązanie: wstaw krytyczny CSS bezpośrednio w HTML (CSS potrzebny do renderowania treści w części widocznej na ekranie) e resztę załaduj asynchronicznie.
// 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
],
},
}),
],
});
Optymalizacja czcionki: Wyeliminuj FOIT na ścieżce krytycznej
Czcionki internetowe często blokują renderowanie tekstu elementu LCP. Jeśli czcionka nie jest
nadal załadowany, przeglądarka czeka wcześniej na (FOIT - Flash of Invisible Text).
renderuj tekst. font-display: swap najpierw pokaż rezerwę
następnie zastępuje, ale tworzy CLS. font-display: optional i wybór
lepsze dla LCP: użyj opcji zastępczej, jeśli czcionka nie jest jeszcze buforowana.
/* 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;
}
Renderowanie po stronie serwera: wyeliminuj wodospad JavaScript
W aplikacjach jednostronicowych (SPA) z renderowaniem po stronie klienta występuje problem strukturalna dla LCP: przeglądarka musi pobrać kod HTML, wykonać JavaScript, wysyłaj żądania do danych, a następnie renderuj zawartość. Ten „wodospad” może dodaj 1-3 sekundy do LCP. Renderowanie po stronie serwera (SSR) rozwiązuje ten problem wysyłanie już wyrenderowanego kodu HTML do klienta.
// 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
Pomiar wpływu: przed i po
// 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)
Lista kontrolna optymalizacji LCP
- Zidentyfikuj element LCP za pomocą DevTools Performance lub WebPageTest
- Dodaj fetchpriority="high" i usuń loading="lazy" z elementu LCP
- W przypadku obrazów: użyj AVIF/WebP, responsywnego zestawu src, jawnych wymiarów
- Wstaw krytyczny CSS w części strony widocznej na ekranie, resztę załaduj asynchronicznie
- Załaduj wstępnie czcionkę używaną przez element LCP
- Jeśli używasz SSR: Upewnij się, że element LCP znajduje się w początkowym kodzie HTML
- Zmierz LCP P75 za pomocą CrUX lub web-vitals.js w produkcji
Wnioski
Optymalizacja LCP to w zasadzie ćwiczenie mające na celu skrócenie czasu na ścieżce krytycznej: każdy zasób, który przeglądarka musi pobrać przed renderowaniem element LCP jest szansą na poprawę. Z fetchpriority, krytycznym CSS inline i SSR, w przypadku typowych połączeń mobilnych można osiągnąć czas LCP poniżej 1 sekundy.







