Aller au contenu

React : performance et déploiement

  1. Mesurer avant d’optimiser (React DevTools Profiler, onglet Performance du navigateur).
  2. Réduire le travail inutile : état au bon endroit, listes avec key, pas de calcul lourd dans le rendu.
  3. Charger moins de JavaScript : découpage du code, dépendances raisonnables.
import { memo, useMemo, useCallback, useState } from 'react';
const Ligne = memo(function Ligne({
nom,
onSupprimer,
}: {
nom: string;
onSupprimer: (nom: string) => void;
}) {
return (
<li>
{nom} <button onClick={() => onSupprimer(nom)}>×</button>
</li>
);
});
export function Liste({ noms }: { noms: string[] }) {
const [filtre, setFiltre] = useState('');
const visibles = useMemo(
() => noms.filter((n) => n.includes(filtre)),
[noms, filtre],
);
const supprimer = useCallback(
(nom: string) => console.log('supprimer', nom),
[],
);
return (
<>
<input value={filtre} onChange={(e) => setFiltre(e.target.value)} />
<ul>
{visibles.map((n) => (
<Ligne key={n} nom={n} onSupprimer={supprimer} />
))}
</ul>
</>
);
}
Outil Rôle
memo(Composant) Évite le rendu si les props n’ont pas changé
useMemo Mémorise un résultat de calcul
useCallback Mémorise une fonction (pour des props de composants memo)

À utiliser là où la mesure montre un gain : ils ajoutent de la complexité. Le compilateur React (React Compiler, installable avec Vite et Babel) automatise cette mémoïsation et réduit ce besoin ; lire sa documentation pour l’activer.

import { lazy, Suspense } from 'react';
const Graphiques = lazy(() => import('./Graphiques'));
export function Tableau() {
return (
<Suspense fallback={<p>Chargement du graphique…</p>}>
<Graphiques />
</Suspense>
);
}

Avec React Router, charger chaque page à la demande (lazy: () => import('./pages/Client')). Le build de Vite produit alors un fichier JavaScript séparé par page.

Pour des milliers de lignes, virtualiser (n’afficher que les lignes visibles) avec une bibliothèque comme TanStack Virtual, et paginer côté API.

Fenêtre de terminal
npm run build
ls -lh dist/assets/
npx vite-bundle-visualizer # carte du contenu des fichiers JavaScript

Les React DevTools (extension du navigateur) affichent les rendus et leur durée. L’onglet Lighthouse des outils de développement évalue performance et accessibilité.

Fenêtre de terminal
npm run build
npm run preview # contrôle local de dist/

dist/ contient index.html et des fichiers dans assets/ dont le nom comprend une empreinte du contenu (index-3f9a2b.js) : ils peuvent être mis en cache durablement.

exemple.com {
root * /var/www/monapp
encode zstd gzip
@assets path /assets/*
header @assets Cache-Control "public, max-age=31536000, immutable"
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
}
handle /api/* {
reverse_proxy 127.0.0.1:3000
}
handle {
try_files {path} /index.html
file_server
}
}
Bloc Rôle
@assets Cache long sur les fichiers à empreinte
handle /api/* Relaie l’API vers le serveur applicatif
try_files {path} /index.html Repli : toute URL inconnue renvoie index.html, pour que React Router gère la route

Ne pas mettre en cache longtemps index.html : il référence les nouveaux fichiers à chaque version. Voir Caddy : exemples réutilisables.

Fenêtre de terminal
npm run build
rsync -az --delete --dry-run dist/ utilisateur@serveur.exemple.com:/var/www/monapp/
rsync -az --delete dist/ utilisateur@serveur.exemple.com:/var/www/monapp/

Toujours lire la sortie du --dry-run. Pour déployer après chaque envoi sur le dépôt : Gitea Actions : exemples.

Les variables VITE_* sont figées dans le JavaScript lors du build : changer la valeur impose de reconstruire. Pour une configuration modifiable sans rebuild, charger un fichier config.json au démarrage :

const config = await fetch('/config.json').then((r) => r.json());
  • Aucun secret dans le code du navigateur (visible de tous).
  • Échapper les contenus : React échappe par défaut ; dangerouslySetInnerHTML n’accepte que du HTML de confiance (ou nettoyé avec DOMPurify).
  • Jetons d’authentification : préférer des cookies HttpOnly et SameSite à localStorage.
  • Mettre à jour les dépendances : npm audit.
  • En-têtes de sécurité (Content-Security-Policy) au niveau du serveur web.
Symptôme Piste
404 en rechargeant une route Repli sur index.html absent (try_files)
Page blanche après déploiement Chemins des assets incorrects (base dans vite.config si l’application est servie dans un sous-dossier), console du navigateur
Ancienne version affichée index.html mis en cache : ne pas lui donner de cache long
Erreur de chargement d’un fichier JavaScript après une mise à jour Onglet ouvert avec l’ancien index.html : recharger
Application lente Profiler, découpage du code, listes virtualisées
Unexpected token '<' pour un fichier JavaScript Le serveur a renvoyé index.html à la place d’un fichier manquant
Appels d’API en échec en production Reverse proxy /api/*, CORS

Ubuntu 24.04 et 26.04 : différences à connaître

Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »

Aucune propre à React. Sous Linux, la casse des noms de fichiers compte dans les imports.