optimisation core web vitals 7 min

Tester les Core Web Vitals dans une VM Ubuntu locale : le piège du dev machine

Votre machine hôte fausse vos mesures de performance. Une VM VirtualBox avec Ubuntu donne un cadre reproductible pour traquer le LCP, le TTFB et les surprises de rendu Linux. Retour d'expérience.

Par Julien Morel
Partager

À chaque fois qu’un site passe de staging à la prod, je redoute le même scénario. Tu lances un Lighthouse sur ton Mac, tout est vert, tu déploies, et le surlendemain la Search Console t’affiche un LCP à 4,2 secondes sur mobile. La différence est rarement dans le code. Elle est dans la machine qui exécute le test. C’est là qu’une VM Ubuntu locale devient une arme anti-fausse-confiance. Pas pour faire joli, pas pour jouer au sysadmin, mais pour coller au plus près du runtime que Googlebot et tes visiteurs sous Linux subissent.

L’environnement local n’est pas un banc de mesure

Ton ordi de dev est un athlète dopé. Processeur qui monte à 4 GHz, 32 Go de RAM, connexion en fibre optique avec 2 ms de latence. Les Core Web Vitals mesurés dans ces conditions donnent l’illusion d’une page parfaite, sauf que ton utilisateur moyen est sur un smartphone Android milieu de gamme, avec un réseau 4G chargé et un CPU bridé après 30 secondes de throttling thermique.

Les outils comme Lighthouse intègrent des simulations, mais elles restent approximatives. Elles throttlent le CPU à un facteur fixe et brident le réseau, sans reproduire la gestion mémoire d’un système Linux low-RAM. Tu peux passer à côté d’un LCP qui explose parce que le navigateur, à court de mémoire, swappe et retarde le décodage d’une image hero.

Construire une VM Ubuntu bridée efface ce biais. Tu lui donnes 2 Go de RAM, deux cœurs, et tu exécutes le même audit, dans les mêmes conditions réseau simulées. Le résultat est souvent un score plus sévère, mais surtout reproductible. C’est cette reproductibilité qui fait défaut au poste de développement.

Construire une VM jetable, reproductible

Le piège avec les VM, c’est d’en faire un clone de son poste, exactement ce qu’on cherche à éviter. Partons d’une image minimale Ubuntu Server 24.04 LTS, sans interface graphique. L’objectif : un terminal, Node.js, un navigateur headless stable, et rien d’autre.

Dans VirtualBox, on règle manuellement la mémoire vidéo à 16 Mo, on désactive l’accélération 3D, et on sélectionne un contrôleur réseau en mode ponté avec un throttling de bande passante. Pour le CPU, on plafonne à 50% d’exécution. La RAM système est limitée à 2 Go, mais on active le swap pour rester dans une réalité plausible.

L’installation se résume à quelques commandes :

sudo apt update && sudo apt install -y curl git
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
sudo apt install -y google-chrome-stable

On installe Lighthouse en global :

npm install -g lighthouse

À partir de là, un snapshot VirtualBox permet de revenir en arrière après chaque test. On obtient un environnement vierge à chaque exécution, sans cache navigateur, sans historique DNS, sans artefacts.

📌 À retenir : Un snapshot avant chaque série d’audits garantit qu’aucun état résiduel ne fausse la mesure du LCP, du TTFB ou de l’INP. C’est l’équivalent d’un cookie jar vide à chaque itération.

Le throttling réseau et CPU que la machine hôte ne te montre jamais

Quand on parle de Core Web Vitals, on pense souvent au poids des bundles JavaScript ou à la taille des images. La latence réseau, elle, reste une variable opératoire mal contrôlée en local. Sur ton poste, un fetch vers une API en localhost prend moins d’une milliseconde. En prod, ce même appel passe par un edge server, traverse plusieurs routeurs, et subit la latence des appareils mobiles.

Dans la VM, on peut reproduire ces conditions. Le mode ponté de VirtualBox permet de conserver l’accès à Internet tout en appliquant un profil réseau lent. Je préfère l’outil tc (traffic control) directement sur l’interface réseau de la VM. Un exemple pour simuler une 4G dégradée :

sudo tc qdisc add dev enp0s3 root netem delay 100ms rate 1.5mbit

Avec 100 ms de latence et un débit limité à 1,5 Mbit/s, le TTFB d’une application Next.js avec rendu par défaut côté serveur prend une claque. Ce que Lighthouse appelait « serveur rapide » sur le poste hôte devient un vrai goulot. La VM rend visible l’impact d’un fetch priority mal configuré ou d’un lazy-loading trop agressif.

Le CPU aussi répond différemment. Un Chromium sous Linux limité à deux cœurs va ralentir l’exécution des scripts de manière non linéaire. Un useEffect qui planifie un setTimeout peut prendre 250 ms de retard alors que la spec en prévoyait 100. L’INP monte mécaniquement.

LCP à 1.2s sur ton MacBook Pro, 3.8s sur la VM à 2 Go

On a reproduit le cas l’année dernière sur une fiche produit e-commerce. Le LCP annoncé par la Search Console sur desktop était de 1,6 seconde en lab data, mais le champ data réel dépassait les 3 secondes. Sur nos machines, impossible de le reproduire.

Dans la VM Ubuntu, avec 2 Go de RAM et un throttling CPU, le LCP passait soudainement à 3,8 secondes. La cause : une image de fond chargée en CSS via background-image et non préchargée. Sur un poste rapide, le CSS était parsé et l’image téléchargée avant que le navigateur n’ait fini de construire le Layout Tree. Avec des ressources limitées, le pipeline de rendu prenait un chemin différent : le Layout était figé avant l’arrivée de l’image, puis un nouveau Layout était déclenché, repoussant le LCP final.

C’est le type de bug invisible sur une machine surpuissante. Sans VM, on aurait conclu que le LCP était acceptable, et on serait passé à côté d’un écart de deux secondes en conditions réelles.

Mesurer le rendu côté client dans un navigateur headless Ubuntu

Une fois la VM paramétrée, on lance l’audit en ligne de commande :

lighthouse https://ton-site-de-staging.com --chrome-flags="--headless --no-sandbox --disable-gpu" --throttling.cpuSlowdownMultiplier=4 --throttling.requestLatencyMs=150 --throttling.downloadThroughputKbps=550 --output html

On économise les ressources en supprimant l’interface graphique. Le navigateur headless suffit pour collecter les métriques. Le flag --no-sandbox est parfois nécessaire dans un conteneur ou une VM non supervisée, même si pour un test local ponctuel on peut s’en passer.

Ce qui change tout, c’est la possibilité de scripter plusieurs runs et de conserver les traces de performance. lighthouse génère un json avec le détail du filmstrip, des long tasks, et des temps de rendu. On le compare ensuite avec les données de web-vitals.js collectées en RUM.

⚠️ Attention : Une VM VirtualBox ajoute une couche d’abstraction GPU qui peut masquer des temps de décodage vidéo ou d’animation CSS. Pour les sites très gourmands en WebGL, l’absence de GPU physique fausse les mesures d’INP. Restez sur du contenu textuel et des images bitmap dans ce type de bench.

Quand ton site se comporte différemment sous Linux

Les polices de caractères sont le serpent caché dans les Core Web Vitals. Sur macOS, les fontes sont souvent préinstallées, ou rendues via un moteur CoreText qui gère bien les graisses variables. Sous Linux, sans les polices Microsoft ou Apple, le navigateur peut tomber sur une police de secours qui modifie la hauteur de ligne, déclenchant du Cumulative Layout Shift.

Dans la VM Ubuntu, on peut tester avec uniquement les polices libres installées par défaut. Le rendu du sous-pixel diffère aussi, surtout si l’accélération est absente. Le LCP d’un bloc de texte peut varier de 200 ms selon la disponibilité d’une fonte web chargée en swap ou block. Une différence que la console de dev de ton Mac ne te montrera jamais parce que la police système sera prise en priorité.

Pour les applications qui utilisent un state management poussé côté client, comme celles conçues avec Zustand, le re-render après hydratation peut également se comporter différemment selon la puissance CPU disponible. La VM expose ces micro-stutters.

Intégrer ce check VM dans ton pipeline local sans ralentir ton workflow

Je ne milite pas pour remplacer tout test local par une VM. C’est un complément ciblé, activé avant les mises en production ou lorsqu’un écart apparaît entre les données lab et field. Un petit script shell suffit.

On clone le snapshot, on démarre la VM, on exécute l’audit Lighthouse via SSH, on récupère le rapport et on éteint la VM. Voici un squelette :

VBoxManage snapshot UbuntuTest restore "clean"
VBoxManage startvm UbuntuTest --type headless
ssh [email protected] 'lighthouse https://staging.example.com --chrome-flags="--headless" --output json > report.json'
scp [email protected]:report.json .
VBoxManage controlvm UbuntuTest acpipowerbutton

Le tout prend deux minutes, le temps d’un café. Pas besoin d’intégration CI complexe. L’avantage c’est la constance des conditions matérielles. Pas de variation due aux mises à jour de l’OS hôte, pas d’indexation Spotlight qui pompe du CPU en arrière-plan.

Certains développeurs préfèrent un setup de développement cloud type GitHub Codespaces. L’inconvénient, c’est une isolation plus faible que la VM et des ressources partagées. Ici, on contrôle la quantité exacte de CPU et de RAM. Dans un conteneur Docker, on pourrait s’approcher, mais la gestion de la mémoire et du swap Linux dans un conteneur reste moins fidèle qu’une VM complète pour reproduire un environnement mobile Android typique. J’ai évoqué ailleurs les différences entre outils comme Claude Code et Cursor, notamment sur la charge mémoire pendant le développement, dans cet article, mais pour le test de performance, la VM reste plus proche du device final.

Questions fréquentes

Est-ce qu’une VM Ubuntu ralentie simule correctement un mobile Android ?

Partiellement. Elle reproduit la contrainte CPU et mémoire, mais pas le throttling thermique spécifique aux chipsets mobiles ni les couches de rendu Android WebView. Pour une simulation mobile plus fine, combinez la VM avec le mode émulation de Chrome DevTools.

Faut-il installer un serveur web directement dans la VM pour tester ?

Ce n’est pas nécessaire si votre site de staging est accessible via le réseau. Mesurer en localhost depuis la VM élimine la latence réseau, ce qui contredit l’objectif de réalisme. Préférez pointer vers l’URL de staging, avec le throttling réseau activé dans la VM.

Est-ce que VirtualBox est le seul hyperviseur valable ?

Non, tout hyperviseur fonctionne. VirtualBox a l’avantage d’être gratuit, cross-platform et scriptable en ligne de commande, ce qui facilite l’intégration dans un workflow automatisé. La logique reste la même avec VMware ou QEMU.

Articles similaires

Julien Morel

Julien Morel

Ancien dev front React passé SEO technique après une migration e-commerce qui a fait perdre 60% du trafic organique à son employeur en une nuit (fichier robots.txt oublié en staging). Depuis, il écrit pour que ça n'arrive à personne d'autre et teste sur ses propres side-projects avant de publier quoi que ce soit.

Cet article est publie a titre informatif. Faites vos propres recherches avant toute decision.