Credit : Logo officiel
Debugger avec les outils DevTools de Chrome
Le collegue qui debug encore avec alert()
J'ai un collegue, je vais l'appeler Marc parce que c'est pas son prenom, qui en 2026 debug encore son JavaScript avec des alert("ici") pose un peu partout dans le code. Quand je lui ai montre les DevTools un soir tard, il m'a dit : "mais en fait ca fait 8 ans que je perds mon temps". Voila. Si vous lisez cet article, c'est peut-etre votre cas. Pas de honte, on rattrape ensemble.
Les Chrome DevTools (et leurs equivalents Edge, Brave, Vivaldi qui partagent le meme moteur) sont l'outil le plus puissant a la disposition d'un developpeur web. Et ils sont gratuits, deja installes, et mis a jour chaque semaine. Ce guide est ce que j'ouvre devant les nouveaux developpeurs en agence quand on debogue ensemble la premiere fois.
Ouvrir les DevTools : F12, Ctrl+Shift+I (Windows/Linux) ou Cmd+Option+I (macOS). Clic droit sur n'importe quel element > Inspecter ouvre directement l'inspecteur centre sur l'element clique.
La Console : bien plus que console.log
La Console est un REPL JavaScript complet sur la page courante. Au-dela du sempiternel console.log() (qui marche tres bien hein), vous avez tout un arsenal sous-utilise :
// Tableau formate, plus lisible que log() pour des objets
console.table([
{ nom: 'Alice', age: 30, role: 'admin' },
{ nom: 'Bob', age: 25, role: 'user' }
]);
// Mesurer le temps d'execution
console.time('fetch-api');
await fetch('/api/products');
console.timeEnd('fetch-api');
// fetch-api: 142.3ms
// Grouper les logs (collapse par defaut avec groupCollapsed)
console.group('Chargement page');
console.log('DOM ready');
console.log('Images chargees');
console.groupEnd();
// Assertion : ne log que si la condition est fausse
console.assert(document.querySelector('.header'), 'Header manquant !');
// Compter les occurrences
console.count('clic bouton');
console.count('clic bouton'); // clic bouton: 2
// Trace de la pile d'appel
console.trace('arrive ici');
// Selecteur CSS shorthand (uniquement dans la console)
$('.mon-element'); // = document.querySelector
$('.mes-elements'); // = document.querySelectorAll (renvoie un tableau, pas une NodeList)
// Inspecter un element selectionne dans l'inspecteur
$0 // dernier element selectionne
$1 // avant-dernier, etc.
Le console.table() a change ma vie pour debugger des reponses d'API. Plus jamais de console.log(JSON.stringify(...)) illisible.
Le live expression
Dans la Console, le bouton oeil cree une Live Expression. Vous tapez par exemple document.querySelectorAll('.error').length et la valeur se met a jour en temps reel pendant que vous interagissez avec la page. Tres pratique pour suivre un compteur, l'etat d'un store Redux ou la position de la souris.
L'onglet Network : 80 % du debug
L'onglet Network enregistre toutes les requetes HTTP, WebSocket et SSE de la page. C'est la que vous passerez la majorite de votre temps de debug.
Filtres et inspection
- Filtrer par type : XHR/Fetch, JS, CSS, Img, Media, Font, Doc, WS
- Filtrer par URL : tapez
domain:api.monsite.frpour ne voir que les requetes vers cet hote - Filtrer par statut :
status-code:500pour traquer les erreurs - Throttling : simule une connexion 3G lente, 4G, ou hors ligne
- Block request URL (clic droit) : bloque une URL pour tester le fallback
Le waterfall revele ce qui ralentit la page :
- Queueing : la requete attend qu'un slot se libere (max 6 connexions par origine en HTTP/1.1)
- TTFB (Time To First Byte) eleve : probleme cote serveur (PHP lent, base de donnees, cache absent)
- Content Download long : le fichier est trop gros, ou la bande passante du serveur est saturee
- Stalled : trop de connexions simultanees au meme domaine
Reproduire en cURL
Clic droit sur une requete > Copy > Copy as cURL. Vous obtenez la commande complete avec headers, cookies et payload. Collez-la dans votre terminal pour reproduire le bug en isolant le frontend :
curl 'https://api.monsite.fr/products' \
-H 'Authorization: Bearer eyJ...' \
-H 'Content-Type: application/json' \
--data-raw '{"category": "shoes"}' \
--compressed
Ca m'a sauve des centaines de fois pour distinguer un bug API d'un bug JS.
L'onglet Performance : profiler le rendu
Quand le site rame visuellement (scroll qui saccade, animations qui sautent), l'onglet Performance enregistre tout ce qui se passe pendant une session :
- Cliquez sur Record
- Interagissez avec la page (scroll, clics, navigation)
- Stop
Vous obtenez :
- Frames : graphique du FPS (60 = fluide, < 30 = saccade visible)
- Main : flame chart des taches sur le thread principal
- Network : les requetes faites pendant l'enregistrement
- Memory : evolution du heap JS
- Layout shifts : les elements qui bougent de maniere inattendue (CLS)
Cherchez les Long Tasks (barres rouges au-dessus de 50 ms). Ce sont elles qui bloquent le thread principal et donnent l'impression que le site est mort. Cliquez dessus pour voir la pile d'appels exacte qui consomme le CPU.
Lighthouse : l'audit en 30 secondes
Lighthouse audite votre page sur 5 axes et vous donne des recommandations actionnables :
- Performance : Core Web Vitals (LCP, INP, CLS), TBT, Speed Index
- Accessibilite : contrastes, labels ARIA, navigation clavier
- Bonnes pratiques : HTTPS, images dimensionnees, console errors
- SEO : meta tags, structure semantique, robots.txt
- PWA : manifest, service worker, installabilite
Pour lancer l'audit :
- Ouvrez l'onglet Lighthouse dans DevTools
- Selectionnez Mobile (par defaut, c'est ce que Google indexe)
- Cochez les categories
- Analyze page load
Chaque recommandation indique l'impact estime en secondes. La derniere fois j'ai gagne 22 points sur la performance d'un site marchand juste en ajoutant les attributs width et height sur les images, ce qui supprime le CLS et permet au navigateur de reserver l'espace avant le chargement.
Lighthouse fonctionne aussi en CLI pour integrer dans CI :
npm install -g lighthouse
lighthouse https://monsite.fr --output=json --output-path=./report.json --chrome-flags="--headless"
Sources : le vrai debugger
L'onglet Sources est ou vous allez quand vous devez vraiment comprendre ce qui se passe dans le code, pas juste constater le resultat.
Breakpoints
Clic sur un numero de ligne pose un breakpoint. Mais vous avez aussi :
- Conditional breakpoint (clic droit > Add conditional breakpoint) : ne s'arrete que si l'expression est vraie. Ideal pour ne pas s'arreter 1000 fois dans une boucle.
- Logpoint : log un message sans modifier le code. Genre
"user.id =", user.idlog la valeur sans s'arreter. - DOM breakpoint (Elements > clic droit sur un noeud > Break on) : s'arrete quand un attribut, le sous-arbre, ou un enfant est modifie.
- XHR/fetch breakpoint : s'arrete quand une URL contenant un fragment donne est appelee.
Dans le code lui-meme :
function processOrder(order) {
if (order.total > 1000) {
debugger; // Le navigateur s'arrete ici si DevTools est ouvert
}
// ...
}
Les raccourcis vitaux
| Raccourci | Action |
|---|---|
| F8 ou Ctrl+\ | Continuer l'execution |
| F10 | Step over (ligne suivante) |
| F11 | Step into (entre dans la fonction) |
| Shift+F11 | Step out (sort de la fonction) |
| Ctrl+P | Ouvrir un fichier par son nom |
| Ctrl+Shift+F | Recherche globale dans toutes les sources |
Les panneaux Watch, Call Stack et Scope vous montrent les valeurs des variables au point d'arret. Closure revele ce qu'une fonction a capture dans sa cloture.
Application : storage, cookies, service workers
L'onglet Application gere tout l'etat persistant de la page :
- Local Storage et Session Storage : visualisez et editez les cles
- Cookies : voyez les cookies, leur Path, Expires, SameSite, HttpOnly. Filtrez par domaine.
- IndexedDB : explorez les bases de donnees, les object stores et les enregistrements
- Service Workers : voyez le SW actif, forcez son update, simulez offline
- Cache Storage : inspectez les caches du Cache API
- Manifest : verifiez le manifest PWA et les icones
Quand un user se plaint d'un bug "je suis deconnecte au refresh", regardez Cookies : il y a souvent un cookie SameSite=None sans Secure qui se fait jeter par les navigateurs recents.
Memory : traquer les fuites memoire
L'onglet Memory permet de capturer des heap snapshots et de comparer l'evolution de la memoire JavaScript dans le temps. Indispensable pour traquer une SPA qui mange 2 Go de RAM apres 30 minutes d'utilisation.
Le workflow type :
- Allez sur la page de l'app dans son etat "baseline"
- Take heap snapshot dans Memory
- Effectuez l'action suspectee de fuiter (ouvrir/fermer une modale 100 fois, naviguer entre routes)
- Take heap snapshot numero 2
- Selectionnez Comparison dans le menu deroulant
Le diff montre les objets crees et non liberes entre les deux snapshots. Filtrer par Detached pour voir les noeuds DOM detaches gardes en memoire par des references oubliees, classique des event listeners non cleanup :
// MAUVAIS : leak memoire
componentDidMount() {
window.addEventListener('resize', this.handleResize);
}
// BON
componentDidMount() {
window.addEventListener('resize', this.handleResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
}
Recorder : automatiser les tests manuels
L'onglet Recorder (assez recent) permet d'enregistrer une serie d'interactions et de les rejouer. Tres utile pour :
- Reproduire un bug complexe a la demande
- Mesurer la performance d'un parcours utilisateur (onglet Performance integre dans Recorder)
- Exporter en script Puppeteer ou Cypress pour automatiser dans la CI
Workflow :
- Onglet Recorder > Create new recording
- Donnez un nom et l'URL de depart
- Cliquez Start recording
- Effectuez vos actions
- End recording
Vous pouvez ensuite Replay ou Export as Puppeteer. Tres pratique en agence pour livrer un test reproductible au QA.
Astuces pro qui font la difference
- Device Mode (
Ctrl+Shift+M) : simule mobile/tablet, change le user-agent, capture une capture d'ecran - Coverage (
Ctrl+Shift+P> Coverage) : montre le pourcentage de CSS et JS reellement utilise sur la page. Souvent 60-70 % du code charge ne sert a rien sur la route courante. - Local Overrides : modifie les fichiers d'un site distant et garde les changements entre rechargements. Pratique pour patcher un bug en prod sans deployer.
- Rendering panel (
Cmd/Ctrl+Shift+P> Rendering) : forceprefers-color-scheme: dark, simule la vision daltonienne, affiche les FPS en temps reel. - Network conditions : custom User-Agent, simule un cache vide, force HTTPS only.
Erreurs courantes et leur fix
"Uncaught ReferenceError: $ is not defined" dans la Console. Vous etes dans un iframe. Selectionnez le contexte d'execution dans le menu deroulant en haut de la Console (par defaut top).
Les breakpoints ne se declenchent pas. Le fichier source est probablement minifie. Cliquez sur l'icone {} en bas du fichier pour le "prettifier". Si vous avez des sourcemaps, verifiez qu'ils sont charges (l'onglet Sources affiche le fichier d'origine).
Lighthouse donne des scores tres differents entre deux runs. Vous etes probablement en mode Navigation avec des extensions Chrome activees. Lancez en navigation privee, ou utilisez le mode Snapshot pour des resultats plus stables.
"CORS error" sans plus d'info dans la Console. Allez dans Network, cliquez sur la requete bloquee, onglet Response : vous verrez souvent un message detaille du serveur (Origin manquante, methode non autorisee, etc.).
La Console affiche "Cross-Origin Read Blocking" sur des images. L'image est servie sans header CORS et vous essayez de la dessiner sur un canvas. Servez-la avec Access-Control-Allow-Origin: * ou rapatriez-la sur votre origine.
Pour aller plus loin
- Optimiser les performances WordPress
- Resoudre les erreurs 502 Bad Gateway sur Nginx
- Configurer la compression gzip et PHP
- Activer le mode debug WordPress
- Mettre en place un CDN gratuit Cloudflare
L'outil que tout le monde a, que personne maitrise
Les DevTools sont gratuits, integres et mis a jour en continu, et pourtant la plupart des developpeurs n'utilisent que 5 % de leurs capacites. Investir une heure a explorer les onglets Network, Performance et Sources est probablement le meilleur retour sur investissement de votre carriere de developpeur. Vous diagnostiquerez en 2 minutes des bugs qui prennent des journees a quelqu'un qui pose des console.log au hasard. Et vous arreterez de mettre des alert() dans votre code, comme Marc.