Tijdens het optimaliseren van een WooCommerce-webshop liepen we tegen iets opvallends aan: productoverzichten en categoriepagina’s waren ineens veel zwaarder dan verwacht.
Niet door grotere afbeeldingen.
Niet door extra CSS.
Niet door een trage server.
Maar door inline JavaScript-state die WooCommerce direct in de eerste HTML-response van de pagina plaatst.
Bij sommige categoriepagina’s zagen we ruim 300KB extra HTML. Dat is fors, zeker omdat dit gebeurt vóórdat de browser externe scripts, stylesheets of afbeeldingen begint te downloaden.
Na verder onderzoek bleek het verschil reproduceerbaar tussen WooCommerce 10.7.0 en WooCommerce 10.8.0.
De korte versie
Vanaf WooCommerce 10.8.0 lijkt de moderne Product Collection / Product Template-block voor elk zichtbaar product volledige productdata in de WordPress Interactivity API-state te laden.
Die data komt terecht in:
wp-script-module-data-@wordpress/interactivity
En daarbinnen vooral in:
state.woocommerce/products.products
Het gevolg: een categoriepagina bevat niet alleen de zichtbare productkaarten, maar ook grote JSON-objecten met productdata. Denk aan prijzen, beschrijvingen, voorraadstatus, categorieën, add-to-cart-data, afbeeldingen, galerijafbeeldingen en responsive image metadata.
Voor een paar producten is dat misschien nog te overzien. Maar op shop- en categoriepagina’s met meerdere producten kan dit snel oplopen tot honderden kilobytes extra HTML.
Wat veranderde er?
De relevante wijziging lijkt te zitten in WooCommerce PR #63662: Refactor iAPI blocks to read product in context.
In WooCommerce 10.7.0 gebruikte de Product Collection-block al de moderne blockstructuur, maar de gedeelde woocommerce/products state bevatte nog geen volledige productobjecten voor alle getoonde producten.
Vanaf WooCommerce 10.8.0 roept ProductTemplate.php voor elk product in de productloop deze functie aan:
wc_interactivity_api_load_product(
'I acknowledge that using experimental APIs means my theme or plugin will inevitably break in the next version of WooCommerce',
$product_id
);
Die functie laadt productdata in de gedeelde Interactivity API-store.
Technisch is dat te begrijpen. WooCommerce beweegt steeds meer richting interactieve blocks, gedeelde frontend-state en modernere client-side interactie.
Maar voor productoverzichten heeft die keuze een duidelijke keerzijde: de eerste HTML-response wordt flink groter.
Onze test
Om dit goed te controleren hebben we een schone WordPress-installatie opgezet met WooCommerce 10.7.0.
Daarin hebben we testproducten aangemaakt met onder andere:
- productafbeeldingen
- galerijafbeeldingen
- beschrijvingen
- korte beschrijvingen
- prijzen
- voorraadstatus
- attributen
- één variabel product
Daarna hebben we dezelfde pagina’s gemeten, WooCommerce geüpdatet naar 10.8.0, en opnieuw gemeten.
| Pagina | WooCommerce 10.7.0 | WooCommerce 10.8.0 |
|---|---|---|
/shop/ | 139.967 bytes | 317.364 bytes |
/product-category/laptops/ | 140.182 bytes | 317.899 bytes |
| Variabele productpagina | 146.492 bytes | 213.799 bytes |
De inline Interactivity API-state groeide op de shop- en categoriepagina’s van ongeveer 1,4KB naar ongeveer 179KB.
Op een echte productcatalogus kan dit nog zwaarder uitpakken. In onze live-omgeving zagen we WooCommerce-pagina’s waarbij de Interactivity API-state rond de 275KB tot 387KB zat.
Dat is alleen de inline state. De rest van de pagina, scripts, stylesheets en afbeeldingen komen daar nog bovenop.
Waarom wordt dit zo groot?
WooCommerce laadt geen echte afbeeldingsbestanden inline in de HTML. Het probleem zit dus niet in de JPG-, PNG- of WebP-bestanden zelf.
Het probleem zit in de metadata.
Een productobject bevat veel meer dan alleen een titel en prijs. Denk bijvoorbeeld aan:
- productnaam
- slug
- permalink
- SKU
- prijsdata
- price HTML
- korte beschrijving
- volledige beschrijving
- categorieën
- tags
- attributen
- voorraadstatus
- add-to-cart-data
- image metadata
- galerijafbeeldingen
- responsive image sizes
- srcsets
Vooral de afbeeldingsdata kan snel groot worden. WordPress genereert vaak meerdere image sizes per afbeelding. Als een product meerdere galerijafbeeldingen heeft, komt daar veel metadata bij kijken.
Bij producten zoals laptops, desktops, onderdelen en accessoires spelen daarnaast vaak ook veel specificaties en attributen mee.
De HTML wordt dus zwaarder voordat de browser überhaupt begint aan de rest van de pagina.
Waarom dit belangrijk is
HTML-grootte telt.
Een zwaardere eerste HTML-response kan invloed hebben op:
- Time to First Byte
- document downloadtijd
- HTML parsing
- geheugenverbruik in de browser
- mobiele prestaties
- cache-efficiëntie
- Core Web Vitals
- crawlers die veel categoriepagina’s bezoeken
Voor kleine webshops lijkt 100KB of 200KB extra misschien niet rampzalig. Maar categoriepagina’s zijn vaak juist de pagina’s die veel verkeer krijgen. Ze worden bezocht door gebruikers, zoekmachines, filters, interne links en soms ook advertentiecampagnes.
Als iedere categoriepagina onnodig honderden kilobytes extra HTML bevat, betaal je die prijs steeds opnieuw.
Dat is precies waarom we bij websites en webshops niet alleen kijken naar hoe een pagina eruitziet, maar ook naar wat er onder de motorkap gebeurt. Een webshop kan visueel netjes zijn en technisch toch onnodig zwaar worden.
En omdat de data inline in het document staat, kun je dit niet simpel oplossen met defer, async of betere image compression. De bytes zitten al in de HTML zelf.
Is dit een bug?
Dat hangt af van je definitie.
De architectuur lijkt bewust gekozen. WooCommerce beweegt richting moderne block-interactie via de WordPress Interactivity API. Daarmee kunnen productblocks onderling state delen. Dat is nuttig voor dynamische productcollecties, filters, add-to-cart-interactie, variaties en client-side navigatie.
Maar de hoeveelheid data die vooraf wordt geladen, lijkt problematisch.
Een categoriepagina heeft meestal geen volledige Store API-achtige productobjecten nodig voor elk zichtbaar product. Voor een productkaart zijn vaak alleen deze gegevens nodig:
- productnaam
- product-URL
- prijs
- primaire afbeelding
- voorraad- of koopstatus
- add-to-cart-informatie
Lange beschrijvingen, volledige galerijen, uitgebreide attributen, alle responsive image metadata en complete productobjecten zijn meestal niet nodig in de eerste HTML-response van een categoriepagina.
Daarom noemen wij dit liever een performance regression dan simpelweg een bug.
De functionaliteit is begrijpelijk. De hoeveelheid data is discutabel.
Variabele producten kunnen extra gevoelig zijn
Variabele producten maken dit nog interessanter.
WooCommerce heeft ook een nieuwere add-to-cart-with-options-route. Voor variabele producten kan het logisch zijn dat de frontend meer informatie nodig heeft. De browser moet immers weten welke variatie hoort bij welke opties, welke prijs daarbij hoort, of de variatie op voorraad is en welke add-to-cart-data nodig is.
Maar ook hier geldt: het verschil zit in hoeveel data vooraf geladen wordt.
Bij een variabel product met veel variaties kan volledige hydratatie van variatieobjecten snel zwaar worden, zeker wanneer variaties eigen afbeeldingen, SKU’s, voorraadstatussen, beschrijvingen of metadata hebben.
Voor één productpagina is dat soms verdedigbaar. Voor een categoriepagina met veel producten wordt het sneller problematisch.
Zelf meten
Je kunt dit vrij eenvoudig op je eigen site controleren.
Download bijvoorbeeld de HTML van een categoriepagina:
curl -s https://jouwdomein.nl/shop/ -o shop.html
Bekijk daarna hoe groot de HTML is:
du -h shop.html
Zoek vervolgens naar de Interactivity API-state:
grep -o "wp-script-module-data-@wordpress/interactivity" shop.html | wc -l
Of zoek specifiek naar WooCommerce product-state:
grep -o "woocommerce/products" shop.html | wc -l
Wil je het preciezer analyseren, kijk dan in de HTML naar:
wp-script-module-data-@wordpress/interactivity
en binnen die JSON naar:
state.woocommerce/products.products
Als daar voor elk zichtbaar product grote objecten staan, heb je waarschijnlijk met hetzelfde gedrag te maken.
Wat kun je eraan doen?
Er zijn grofweg drie routes.
1. Accepteren
Als je catalogus klein is, je caching goed staat en je categoriepagina’s nog snel genoeg zijn, kun je dit laten zitten.
Je profiteert dan maximaal van WooCommerce’s moderne blockarchitectuur en hoeft geen afwijkende templates te onderhouden.
Voor kleine shops of pagina’s met weinig producten kan dat prima zijn.
2. Wachten op WooCommerce-optimalisaties
WooCommerce zou dit kunnen verbeteren door op productarchieven een kleinere productvorm te hydrateren.
Bijvoorbeeld:
- alleen data laden die zichtbare blocks daadwerkelijk nodig hebben
- zware productdata pas laden bij interactie
- galerijdata niet standaard in archive views plaatsen
- beschrijvingen en uitgebreide attributen niet inline hydratieren op categoriepagina’s
- variatiedata alleen laden wanneer de gebruiker opties kiest
Op die manier behoudt WooCommerce de voordelen van moderne interactieve blocks, zonder de eerste HTML-response onnodig zwaar te maken.
3. Server-rendered WooCommerce-templates gebruiken
Voor veel webshops is dit waarschijnlijk de meest praktische route.
Een klassieke of custom server-rendered productloop kan nog steeds prima werken met:
- productkaarten
- sortering
- paginering
- prijzen
- voorraadlabels
- add-to-cart-knoppen
- SEO-vriendelijke markup
Maar zonder volledige productobjecten inline in de HTML te plaatsen.
Voor SEO, performance en voorspelbaarheid is dat vaak een betere trade-off dan een zwaardere app-achtige categoriepagina.
Dat betekent niet dat moderne WooCommerce-blocks slecht zijn. Het betekent wel dat je bij grotere catalogi goed moet meten wat ze doen met je HTML-output.
Bij webshopontwikkeling is dit precies het soort keuze dat verschil maakt: niet alleen een plugin installeren en hopen dat het snel genoeg is, maar bewust bepalen welke techniek past bij de inhoud, het aantal producten en het gedrag van bezoekers.
Onze conclusie
WooCommerce 10.8.0 introduceert een duidelijke HTML-size regression voor productoverzichten die moderne Product Collection-blocks gebruiken.
De wijziging lijkt voort te komen uit een bewuste architectuurrichting: gedeelde productstate via de WordPress Interactivity API. Dat is technisch interessant en kan functioneel waardevol zijn.
Maar in de huidige vorm kan die state veel meer data bevatten dan een categoriepagina nodig heeft.
Voor webshops met productcategorieën, veel productafbeeldingen, veel attributen of variabele producten is dit absoluut de moeite waard om te meten.
Wij hebben hiervoor een issue geopend bij WooCommerce: WooCommerce 10.8 performance regression: Product Collection hydrates full product objects into initial HTML.
Hopelijk leidt dit tot een optimalisatie waarbij WooCommerce de voordelen van moderne interactieve blocks behoudt, maar de eerste HTML-response weer slanker wordt.
Want moderne frontend-interactie is mooi. Maar niet als iedere categoriepagina daar honderden kilobytes extra HTML voor moet meesturen.
Laat je webshop niet onnodig zwaar worden
Een snelle webshop begint niet bij één cacheplugin of één vinkje in de hostingomgeving. Het begint bij meten, begrijpen en daarna gericht verbeteren.
Soms zit de winst in betere hosting. Soms in caching. Soms in afbeeldingen. En soms, zoals in dit geval, in de manier waarop WooCommerce zelf de pagina opbouwt.
Bij Forcys helpen we bedrijven met snelle, stabiele en praktische websites en webshops. We kijken niet alleen naar de voorkant, maar ook naar performance, onderhoudbaarheid, SEO en de technische keuzes achter de site.
Wil je weten of jouw WordPress- of WooCommerce-site onnodig traag of zwaar is? Neem dan contact met ons op via forcys.nl/contact. Dan kijken we graag met je mee.