Core Web Vitals begrijpen
Google meet je website op drie cruciale metrics. Als je deze begrijpt, weet je precies waar je moet optimaliseren:
LCP (Largest Contentful Paint)
Doel: < 2.5sWanneer het grootste element zichtbaar is. Meestal een hero image of heading.
- Impact: 25% van score
- Oorzaken: trage server, render-blocking resources
- Fix: preload, critical CSS
INP (Interaction to Next Paint)
Doel: < 200msHoe snel reageert de pagina op gebruikersinteractie (vervangt FID in 2024).
- Impact: 25% van score
- Oorzaken: zware JavaScript
- Fix: code splitting, defer
CLS (Cumulative Layout Shift)
Doel: < 0.1Hoeveel verschuift de layout tijdens het laden?
- Impact: 25% van score
- Oorzaken: images zonder dimensies, late-loading ads
- Fix: aspect-ratio, font-display
Critical CSS: De #1 LCP killer
Dit is de belangrijkste optimalisatie die 90% van de WordPress sites mist. Critical CSS is de minimale CSS die nodig is om de "above the fold" content te renderen, inline in je <head>.
Waarom is dit zo belangrijk?
Standaard blokkeert je CSS-bestand de rendering. De browser wacht tot het hele bestand is gedownload voordat hij iets toont. Met Critical CSS zie je direct content.
<head>
<link rel="stylesheet" href="style.css"> <!-- BLOKKEERT RENDERING -->
</head>
Tijdlijn: [----Download CSS----][--Parse--][RENDER]
0ms 800ms 1000ms = LCP 1000ms+
<head>
<style>
/* Alleen above-the-fold CSS - ~15KB */
.header{...} .hero{...} .nav{...}
</style>
<link rel="preload" href="style.css" as="style"
onload="this.onload=null;this.rel='stylesheet'">
</head>
Tijdlijn: [RENDER][----Download CSS in background----]
200ms = LCP 200ms!
Hoe genereer je Critical CSS?
WP Rocket
AutomatischGenereert automatisch Critical CSS per pagina.
- Instellingen → Optimize CSS
- "Remove Unused CSS" aan
- Automatische regeneratie
FlyingPress
Beste resultaatNieuwere technologie, vaak betere scores.
- Genereert per post type
- Unused CSS removal
- Kleinere output
Perfmatters + CriticalCSS.com
Pro setupVoor maximale controle.
- API-based generatie
- Handmatige fallback
- Beste voor complexe sites
JavaScript optimalisatie
JavaScript is de grootste vijand van je INP score. Elke KB JavaScript moet worden gedownload, geparsed en uitgevoerd voordat je pagina interactief is.
1. Delay JavaScript execution
Dit is de meest impactvolle JS-optimalisatie. In plaats van alle scripts te laden bij pageload, wacht je tot de gebruiker interactie heeft (scroll, click, touch).
// Handmatige delay (voor custom implementaties)
const loadScriptsOnInteraction = () => {
// Laad je scripts hier
const script = document.createElement('script');
script.src = 'heavy-script.js';
document.body.appendChild(script);
};
// Trigger op eerste interactie
['scroll', 'click', 'touchstart', 'mousemove'].forEach(event => {
window.addEventListener(event, loadScriptsOnInteraction, { once: true });
});
// Fallback na 5 seconden
setTimeout(loadScriptsOnInteraction, 5000);
2. Scripts die je NOOIT moet delayen:
- jQuery (als je thema het nodig heeft voor basisnavigatie)
- Analytics/Tag Manager (voeg toe aan exclusielijst)
- Consent management (cookie banners)
- Chat widgets die direct zichtbaar moeten zijn
3. Specifieke plugin optimalisaties:
// Verwijder WooCommerce scripts van niet-shop pagina's
add_action('wp_enqueue_scripts', function() {
if (!is_woocommerce() && !is_cart() && !is_checkout()) {
wp_dequeue_style('woocommerce-general');
wp_dequeue_style('woocommerce-layout');
wp_dequeue_script('wc-cart-fragments');
wp_dequeue_script('woocommerce');
}
}, 99);
// Verwijder Gutenberg block CSS als je Classic Editor gebruikt
add_action('wp_enqueue_scripts', function() {
wp_dequeue_style('wp-block-library');
wp_dequeue_style('wp-block-library-theme');
wp_dequeue_style('wc-blocks-style');
}, 100);
// Verwijder jQuery Migrate (meestal niet nodig)
add_action('wp_default_scripts', function($scripts) {
if (!is_admin() && isset($scripts->registered['jquery'])) {
$script = $scripts->registered['jquery'];
if ($script->deps) {
$script->deps = array_diff($script->deps, ['jquery-migrate']);
}
}
});
Moderne image optimalisatie
Afbeeldingen zijn meestal 50%+ van je pageweight. De juiste optimalisatie kan je LCP dramatisch verbeteren.
1. Gebruik moderne formats (AVIF > WebP > JPEG)
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="..." width="800" height="600"
loading="lazy" decoding="async">
</picture>
/* Besparingen:
JPEG: 100KB (baseline)
WebP: 70KB (-30%)
AVIF: 45KB (-55%) */
2. Preload je LCP image
De afbeelding die je LCP bepaalt (meestal hero image) moet gepreload worden:
<head>
<!-- Preload met moderne format support -->
<link rel="preload" as="image" href="hero.avif"
type="image/avif"
imagesrcset="hero-400.avif 400w, hero-800.avif 800w, hero-1200.avif 1200w"
imagesizes="100vw">
</head>
// Of via PHP voor dynamische hero images:
add_action('wp_head', function() {
if (is_front_page() && has_post_thumbnail()) {
$img = wp_get_attachment_image_src(get_post_thumbnail_id(), 'full');
echo '<link rel="preload" as="image" href="' . $img[0] . '">';
}
}, 1);
3. Fetchpriority voor kritieke images
<!-- LCP image: hoge prioriteit, geen lazy loading -->
<img src="hero.webp"
fetchpriority="high"
decoding="sync"
alt="Hero">
<!-- Overige images: lazy loading -->
<img src="other.webp"
loading="lazy"
decoding="async"
fetchpriority="low"
alt="Other">
Font loading strategieen
Fonts zijn vaak de oorzaak van CLS (layout shift) en kunnen je LCP vertragen. Hier zijn de PRO-technieken:
1. Self-host Google Fonts
Google Fonts van fonts.googleapis.com vereist 2 extra DNS lookups en connections. Self-hosting is sneller:
/* 1. Preload je belangrijkste font weight */
<link rel="preload" href="/fonts/inter-400.woff2"
as="font" type="font/woff2" crossorigin>
/* 2. Font-face met font-display: swap */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-400.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap; /* Voorkomt FOIT, maar kan CLS veroorzaken */
}
/* 3. Beter: font-display: optional (geen CLS!) */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-400.woff2') format('woff2');
font-weight: 400;
font-display: optional; /* Gebruikt systeemfont als niet in cache */
}
2. Fallback font matching
De grootste CLS-oorzaak is het verschil tussen je fallback font en web font. Match ze:
/* Definieer een aangepaste fallback */
@font-face {
font-family: 'Inter-fallback';
src: local('Arial');
size-adjust: 107%; /* Match de breedte */
ascent-override: 90%; /* Match de hoogte */
descent-override: 22%;
line-gap-override: 0%;
}
body {
font-family: 'Inter', 'Inter-fallback', sans-serif;
}
/* Tool om values te berekenen: https://screenspan.net/fallback */
Geavanceerde caching
Caching is meer dan alleen een plugin installeren. Hier zijn de lagen die je nodig hebt:
De caching stack (van snel naar langzaam):
-
1
Browser cache (client-side)
Cache-Control headers voor statische assets. Stel in op 1 jaar voor assets met hash in filename.
-
2
CDN Edge cache (Cloudflare/BunnyCDN)
Serveert content vanaf locatie dichtbij de bezoeker. Reduceert TTFB drastisch.
-
3
Page cache (WP Rocket/FlyingPress)
Slaat complete HTML op. Voorkomt PHP execution voor elke request.
-
4
Object cache (Redis/Memcached)
Cached database queries. Cruciaal voor dynamic content en logged-in users.
-
5
Opcode cache (OPcache)
Cached compiled PHP. Meestal standaard aan bij goede hosts.
# Agressieve caching voor statische assets
<IfModule mod_expires.c>
ExpiresActive On
# Images
ExpiresByType image/avif "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
# Fonts
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
# CSS/JS (met versioning)
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
# HTML (kort)
ExpiresByType text/html "access plus 0 seconds"
</IfModule>
# Immutable voor gehashte assets
<FilesMatch "\.[a-f0-9]{8,}\.(css|js|woff2|avif|webp)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
Database optimalisatie
Een opgeblazen database vertraagt elke uncached request. Dit zijn de technieken die echt helpen:
1. Verwijder bloat
-- Verwijder post revisions (bewaar laatste 3)
DELETE FROM wp_posts WHERE post_type = 'revision'
AND ID NOT IN (
SELECT * FROM (
SELECT ID FROM wp_posts WHERE post_type = 'revision'
ORDER BY post_date DESC LIMIT 3
) AS t
);
-- Verwijder auto-drafts ouder dan 7 dagen
DELETE FROM wp_posts WHERE post_status = 'auto-draft'
AND post_date < DATE_SUB(NOW(), INTERVAL 7 DAY);
-- Verwijder orphaned postmeta
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;
-- Verwijder transients (worden toch geregenereerd)
DELETE FROM wp_options WHERE option_name LIKE '%_transient_%';
-- Optimaliseer tabellen
OPTIMIZE TABLE wp_posts, wp_postmeta, wp_options, wp_comments;
2. Beperk revisions in wp-config.php
// Beperk revisions tot 3
define('WP_POST_REVISIONS', 3);
// Verleng autosave interval (default 60 seconden)
define('AUTOSAVE_INTERVAL', 300);
// Disable heartbeat op frontend (bespaart AJAX calls)
add_action('init', function() {
if (!is_admin()) {
wp_deregister_script('heartbeat');
}
});
3. Autoload optimalisatie
De wp_options tabel met autoload='yes' wordt bij ELKE pageload geladen. Check welke opties je kunt uitzetten:
-- Check totale autoload grootte (moet < 1MB zijn)
SELECT SUM(LENGTH(option_value)) as autoload_size
FROM wp_options WHERE autoload = 'yes';
-- Vind de grootste autoloaded options
SELECT option_name, LENGTH(option_value) as size
FROM wp_options
WHERE autoload = 'yes'
ORDER BY size DESC LIMIT 20;
-- Zet grote opties op autoload=no (voorzichtig!)
UPDATE wp_options SET autoload = 'no'
WHERE option_name = 'example_large_option';
Server-side optimalisaties
Je kunt alles optimaliseren, maar op slechte hosting haal je nooit een goede score. Dit is wat je nodig hebt:
Minimale server requirements voor 90+ scores:
-
PHP 8.1+ met OPcache PHP 8.2 is 5-10% sneller dan 8.0
-
NVMe SSD storage 10x sneller dan traditionele SSD
-
Redis/Memcached object cache Cruciaal voor dynamic content
-
HTTP/2 of HTTP/3 (QUIC) Parallelle requests, snellere handshakes
-
Server in EU (voor NL bezoekers) Lage latency = lage TTFB
TTFB (Time to First Byte) optimaliseren
Je TTFB moet onder 200ms zijn. Check dit met:
# Check TTFB (time_starttransfer)
curl -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" -o /dev/null -s https://jouwsite.nl
# Verwachte output voor snelle site:
# DNS: 0.020s
# Connect: 0.040s
# TTFB: 0.150s <-- Dit moet < 200ms zijn
# Total: 0.300s
De beste performance plugins
Na jaren testen, dit zijn onze aanbevelingen:
FlyingPress
Beste overallNieuwste technologie, consistent beste scores.
- Critical CSS per page type
- JS delay + exclude
- Unused CSS removal
- Image CDN optioneel
- €60/jaar
WP Rocket
Meest populairBetrouwbaar, goede support, breed inzetbaar.
- Page cache + preload
- Remove unused CSS
- Delay JavaScript
- Lazy loading
- €59/jaar
Perfmatters
AanvullingScript manager - gebruik naast caching plugin.
- Scripts per pagina aan/uit
- Local Google Analytics
- Database cleaner
- Preloading controls
- €25/jaar
Veelgestelde vragen
Waarom is mijn mobile score zoveel lager dan desktop?
PageSpeed simuleert een mid-range Android telefoon op 4G. Dit is veel trager dan je eigen telefoon. De test gebruikt CPU throttling (4x langzamer) en netwerk throttling (1.6 Mbps). Focus op mobile - als die goed scoort, is desktop automatisch goed.
Kan ik 100/100 halen?
Technisch mogelijk, maar vaak niet praktisch. 90+ is "groen" en geeft geen ranking nadeel. De laatste 10 punten kosten disproportioneel veel moeite en kunnen functionaliteit breken. Focus op echte gebruikerservaring, niet het perfecte nummer.
Wat is belangrijker: score of echte laadtijd?
Echte laadtijd (en vooral perceived performance). PageSpeed is een indicator, maar geen perfecte meting. Gebruik ook tools als WebPageTest voor real-world metingen en Google Search Console voor field data (echte gebruikers).
Mijn score fluctueert - is dat normaal?
Ja, 5-10 punten variatie is normaal. PageSpeed test vanaf Google servers die variëren in locatie en load. Test altijd meerdere keren en kijk naar het gemiddelde. GTmetrix biedt consistentere tests omdat je de testlocatie kunt fixeren.
Complete optimalisatie checklist
Print deze checklist en werk hem af voor elke website:
PageSpeed 90+ Checklist
Geen tijd voor optimalisatie?
Wij optimaliseren dagelijks WordPress websites naar 90+ scores. Laat ons het zware werk doen.