LCP-optimalisatie: vooraf laden van afbeeldingen, kritische CSS en SSR
Il Grootste inhoudsvolle verf (LCP) meet de tijd die verstrijkt vanaf het laden van de pagina tot het moment dat het grootste element zichtbaar is in de zichtvenster wordt weergegeven. Google beschouwt een LCP van minder dan 2,5 seconden als "goed", tussen 2,5 en 4 seconden "te verbeteren", meer dan 4 seconden "slecht". Het is een van de drie Core Web Vitals die rechtstreeks van invloed zijn op de zoekresultaten.
Het optimaliseren van het LCP vereist inzicht in de kritisch pad: de volgorde aantal bewerkingen die de browser moet voltooien voordat hij het element kan weergeven LCP. Eventuele onnodige bronnen op het kritieke pad vertragen het LCP. De vier strategieën grotere impact: vooraf laden van afbeeldingen, kritische inline CSS, optimalisatie aantal lettertypen en server-side rendering — verlaag de LCP in de meeste gevallen met 500 ms-2 seconden onderdeel van echte gevallen.
Wat je gaat leren
- Hoe de browser het LCP-element ontdekt en laadt: het kritieke pad
- fetchpriority="high": vertel de browser welke afbeelding prioriteit heeft
- rel="preload": Laad bronnen vooraf voordat de parser ze ontdekt
- Kritieke CSS inline: elimineer weergaveblokkering van stylesheets
- font-display: wisselen en optioneel om FOIT te voorkomen, wat de LCP vertraagt
- Rendering op serverzijde: Elimineer waterval-JS voor LCP
- Meet de echte impact met WebPageTest en PerformanceObserver
Het kritieke pad voor het LCP
Voordat u gaat optimaliseren, moet u begrijpen wat het LCP in uw specifieke geval blokkeert. De browser volgt deze stappen om het LCP-element weer te geven:
// 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": expliciete browserprioriteit
De browser gebruikt een intern prioriteitssysteem om te beslissen welke bronnen moeten worden geladen
voor. Standaard hebben afbeeldingen een lage of gemiddelde prioriteit. Het attribuut
fetchpriority="high" vertelt de browser dat deze afbeelding het LCP is
element en moet eerst worden geladen.
Kritieke CSS Inline: Elimineer weergaveblokkering
Externe stylesheets blokkeren de weergave totdat ze worden gedownload en geparseerd. Een langzaam netwerk of een trage server kan het LCP slechts met 500 ms-2 seconden vertragen voor een CSS-bestand. De oplossing: inline de kritische CSS direct in HTML (de CSS die nodig is om inhoud boven de vouw weer te geven) e laad de rest asynchroon.
// 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
],
},
}),
],
});
Lettertype-optimalisatie: elimineer FOIT op het kritieke pad
Weblettertypen blokkeren vaak de weergave van LCP-elementtekst. Als het lettertype dat niet is
nog steeds geladen, wacht de browser eerder op (FOIT - Flash of Invisible Text).
de tekst weergeven. font-display: swap laat eerst de terugval zien
vervangt vervolgens, maar creëert een CLS. font-display: optional en keuze
beter voor LCP: gebruik fallback als het lettertype nog niet in de cache staat.
/* 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;
}
Rendering op de server: Elimineer JavaScript-waterval
Single Page Applications (SPA's) met weergave aan de clientzijde hebben een probleem structureel voor het LCP: de browser moet de HTML downloaden, JavaScript uitvoeren, verzoeken indienen bij de gegevens en vervolgens de inhoud weergeven. Deze "waterval" kan voeg 1-3 seconden toe aan het LCP. Server Side Rendering (SSR) lost dit op het verzenden van reeds gerenderde HTML naar de client.
// 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
Impact meten: voor en na
// 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)
Controlelijst voor LCP-optimalisatie
- Identificeer het LCP-element met DevTools Performance of WebPageTest
- Voeg fetchpriority="high" toe en verwijder load="lazy" uit het LCP-element
- Voor afbeeldingen: gebruik AVIF/WebP, responsive srcset, expliciete afmetingen
- Plaats de kritische CSS boven de vouw en laad de rest asynchroon
- Laad het lettertype dat door het LCP-element wordt gebruikt vooraf
- Als u SSR gebruikt: Zorg ervoor dat het LCP-element in de initiële HTML staat
- Meet LCP P75 met CrUX of web-vitals.js in productie
Conclusies
LCP-optimalisatie is in feite een oefening in het reduceren van tijd op het kritieke pad: elke bron die de browser moet downloaden voordat deze wordt weergegeven het LCP-element is een kans voor verbetering. Met fetchprioriteit, kritische CSS inline en SSR kunt u LCP's van minder dan 1 seconde bereiken op typische mobiele verbindingen.







