Améliorer la performance d’une app React Router 7 : la méthode
Découvre comment booster le SEO et la vitesse de ton app React Router 7 : checklist, TTFB, bundle JS, images, scripts et astuces concrètes.
Mesurer d’abord, optimiser ensuite
Avant de toucher une seule ligne de code, ouvre le laboratoire de référence : PageSpeed Insights. Copie l’URL de ta prod et regarde la couleur du voyant :
- vert ≥ 90 : tu peux encore gratter quelques ms, mais rien d’urgent ;
- orange 50-89 : c’est la zone où 80 % des sites stagnent – on veut la dépasser ;
- rouge < 50 : Google te pénalise déjà, tes utilisateurs aussi.
Dans la vidéo du transcript j’ai scanné algomax.fr : 35/100 mobile. Pourquoi ? Principalement :
- TTFB d’1,5 s : serveur et requêtes BDD lents.
- Vidéo de 7 Mo en fond.
- Scripts tiers (Google Analytics, reCAPTCHA, Facebook Pixel) chargés trois fois.
On va voir comment corriger ces points dans un projet React Router 7.
Réduire le Time To First Byte (TTFB)
Le TTFB dépend de deux facteurs : – la puissance du VPS ; – le travail que fait ton loader avant de rendre le HTML.
1. Garde les requêtes critiques dans les loaders parents
1export async function loader() {2// ^? Appelé *à chaque* navigation imbriquée3return {4user: await getOptionalUser(),5// pas de requête lourde ici ! <──6};7}
Place la requête article, produit, etc. dans la route feuille ; ainsi la page d’accueil ne paye pas cette facture.
2. Supprime les “sleep” déguisés
1- await new Promise((r) => setTimeout(r, 500)) // debug oublié 😱
Ces micro‐latences sont invisibles en dev mais mortelles en prod.
Alléger le JavaScript client
Active le split route modules
Depuis React Router v7.3, un flag compile un chunk par route :
1export default {2future: {3unstable_splitRouteModules: true, // ✂️ 1 fois, puis on oublie4},5} as const;
Résultat : la page “/blog” ne télécharge pas le code du tableau de bord.
Charge les scripts tiers en Web Worker (Partytown)
1npm i @builder.io/partytown
1import { Partytown } from "@builder.io/partytown/react";23export function Layout({ children }: { children: React.ReactNode }) {4return (5<html lang="fr">6<head>7{/* Scripts tiers déplacés vers Partytown */}8<Partytown debug={false} forward={["dataLayer.push"]} />9</head>10<body>{children}</body>11</html>12);13}
Tu continueras d’utiliser window.dataLayer.push() (Google Tag Manager),
mais le thread principal reste libre : +5-10 pts PageSpeed.
Warning
Optimiser les images (le vrai “gros” de ta note)
Utilise un CDN d’images
Cloudflare Images ou ImageKit génèrent une miniature adaptée à la taille de l’écran :
1const cdn = "https://ik.imagekit.io/algomax/tr:w-640/";2export function Img({ src, alt }: { src: string; alt: string }) {3return <img src={cdn + src} alt={alt} width={640} height={360} loading="lazy" />;4}
Précharge la bannière au LCP
1export const links: LinksFunction = () => [2{ rel: "preload", as: "image", href: "/images/hero.webp" },3];
Google comptabilise cette image comme Largest Contentful Paint ; gagne 200 ms rien qu’en la déclarant.
Mettre le CSS et les polices dans la fast-lane
1export const links: LinksFunction = () => [2{ rel: "preconnect", href: "https://fonts.googleapis.com" },3{ rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" },4{ rel: "preload", as: "style", href: "/styles/app.css" },5];
Couplé avec les leçons « Précharger un fichier CSS » et « Headers Cache-Control », ton CSS est prêt avant même que le HTML arrive.
Déléguer les assets statiques à Caddy
1@static path *.css *.js *.webp *.png *.svg2handle @static {3root * /var/www/rr7/public4file_server5header Cache-Control "public, max-age=31536000, immutable"6}
Ton conteneur React Router ne sert plus les images : CPU économisé.
Le header immutable permet à Chrome de garder le fichier 1 an.
Nettoyer les librairies inutilisées
Analyse le bundle avec source-map-explorer.
1npm i -D source-map-explorer2npm run build3npx source-map-explorer build/client/**/*.js
Dans la vidéo, reCAPTCHA pesait 14 % du bundle et était chargé 3 fois. ✅ Solution : Partytown + suppression des imports dupliqués.
Checklist « Performance » à épingler
1- [ ] TTFB < 500 ms (PageSpeed / WebPageTest)2- [ ] LCP < 2,5 s sur mobile3- [ ] Bundle JS < 150 kB gzippé4- [ ] Aucune image > 500 kB non optimisée5- [ ] Header Cache-Control présent sur CSS/JS/images6- [ ] Scripts tiers déportés en Web Worker7- [ ] Preload des assets critiques (CSS, font, LCP)
Important
Teste à chaque merge : un simple import mal placé peut faire gonfler le
bundle de 50 kB et faire passer ton LCP de 2,1 s à 3,8 s.
Automatise avec Lighthouse CI ou PageSpeed GitHub Action.
Ressources externes
- PageSpeed Insights – l’outil de base.
- Partytown – docus & intégrations.
- Source Map Explorer – visualiser le poids de chaque dépendance.
- Web Vitals – explications officielles Google.
Conclusion
La performance n’est pas une cerise décorative : c’est un facteur de positionnement SEO et de conversion. Avec React Router 7 tu disposes de :
- loaders côté serveur pour envoyer uniquement le HTML utile ;
- un plugin Vite pour découper ton bundle ;
- la simplicité de Partytown pour caser les scripts marketing hors du main thread.
Applique la checklist, repasse un coup de PageSpeed et vise le green zone ! Ton futur toi et tes visiteurs te diront merci.
Comprendre les concepts fondamentaux
Quelle est la principale différence entre les composants client et serveur dans React ?
Optimisation des performances
Quelle technique est recommandée pour éviter les rendus inutiles dans React ?
Architecture des données
Quel hook permet de gérer les effets de bord dans un composant React ?