Notes pratiques : Comment j’ai optimisé une application React lente sans la réécrire
Guide pratique pas à pas : Comment j’ai optimisé une application React lente sans la réécrire – contrats, vérifications et emplacements de code intégrable pour les équipes utilisant ce modèle.
Utilisez ceci comme une version révisée destinée aux opérateurs des idées présentées dans « Comment j’ai optimisé une application React lente sans la réécrire » : étapes claires, emplacements de code ordonnés et notes de récupération qui survivent au transfert de responsabilités. L’étape « Aperçu » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définez des critères de succès et refusez toute mise en œuvre partielle silencieuse.
Le diagnostic : identifier le problème
Pour déterminer le stade du diagnostic, il faut définir les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu, sans avoir à deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût permet d’éviter des factures inattendues lorsque le parcours passe de l’environnement de démonstration à des environnements partagés. Placez l’état au même endroit que le composant responsable de sa modification ; placer tout dans un stockage global rend plus difficiles à détecter les erreurs liées aux temps d’exécution.
1. React.memo : La solution la plus simple
Pour le mémo React, définissez les entrées, l’élément responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Placez l’état avec le composant responsable de la mutation. Mettre tout dans un stockage global rend les erreurs liées aux délais plus difficiles à détecter.
const ExpensiveComponent = React.memo(({ data, onUpdate }) => {
// Component logic
});
2. useMemo et useCallback : Arrêter les recalculs récursifs
Pour les étapes useMemo et useCallback, définissez les entrées, le responsable de l’étape ainsi que les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez conjointement le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’améliorations ultérieures. Placez l’état au même endroit que le composant responsable de la mutation. Mettre tout dans un stockage global rend les erreurs liées aux délais plus difficiles à détecter. Pour les étapes useMemo et useCallback, définissez les entrées, le responsable de l’étape ainsi que les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez les terminations partielles silencieuses.
const computedStats = useMemo(() => {
return expensiveAggregation(data);
}, [data]);
const handleUpdate = useCallback((id) => {
updateItem(id);
}, []);
3. useTransition : Prioriser les interactions utilisateur
Lors de la phase 3 « useTransition : Prioriser les interactions utilisateur », notez d’abord le contrat requis : les entrées nécessaires, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût évite des factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés. Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.
const [isPending, startTransition] = useTransition();
const handleSearch = (term) => {
startTransition(() => {
setSearchTerm(term);
// Filtering happens in the background
});
};
4. useDeferredValue : Atténuer les rendus coûteux
Lorsque vous travaillez sur l’étape 4 « Smoothing Out avec useDeferredValue », notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système. Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées pendant le rendu.
const deferredData = useDeferredValue(data);
// Chart receives deferredData and updates only when React has idle time
5. Virtualisation : ne rendre que ce qui est visible
Lors du travail sur l’étape 5 « Seulement rendu par virtualisation », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations apportées ultérieurement. Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées pendant le rendu. Lors du travail sur l’étape 5 « Seulement rendu par virtualisation », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Traitez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des contrôles de succès et refusez les terminations partielles silencieuses.
import { FixedSizeList } from 'react-window';
const Row = ({ index, style }) => (
<div style={style}>
{data[index].name}
</div>
);
<FixedSizeList
height={400}
itemCount={data.length}
itemSize={35}
width="100%"
>
{Row}
</FixedSizeList>
6. Chargement différé : Séparation du code par route
La phase 6 de chargement différé fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple réussi, un cas d’échec ainsi que des notes de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût permet d’éviter des factures inattendues lorsque le chemin passe de l’environnement de démonstration à des environnements partagés. Maintenez les opérations de rendu peu coûteuses et reportez les calculs onéreux à la mise en mémoire après avoir effectué des mesures. Une mise en mémoire prématurée peut cacher des bugs liés à des propriétés obsolètes.
const Dashboard = lazy(() => import('./views/Dashboard'));
const Analytics = lazy(() => import('./views/Analytics'));
function App() {
return (
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/analytics" element={<Analytics />} />
</Routes>
</Suspense>
);
}
7. useMemoizedSelector : Optimisation de la gestion de l’état
La phase 7 de gestion d’état useMemoizedSelector fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple réussi, un cas d’échec et la note de réversion avant d’élargir le périmètre. Conservez les configurations en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Maintenez le processus de rendu léger et reportez les calculs coûteux à l’après-mémoisation, uniquement après avoir effectué des mesures. Une mémoisation prématurée peut cacher des erreurs liées à des props obsolètes.
import { createSelector } from '@reduxjs/toolkit';
const selectFilteredData = createSelector(
(state) => state.items,
(state) => state.filterTerm,
(items, term) => items.filter(item =>
item.name.toLowerCase().includes(term.toLowerCase())
)
);
// In component:
const filteredData = useSelector(selectFilteredData);
Les chiffres : avant et après
La phase « The Numbers Before » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez en même temps le parcours réussi et celui de récupération. Les tentatives répétées, les contrôles humains et le traitement des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Gardez les tâches de rendu peu coûteuses et reportez les calculs onéreux à la mise en mémoire uniquement après avoir effectué des mesures ; une mise en mémoire prématurée peut cacher des bugs liés à des données obsolètes. La phase « The Numbers Before » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définites des critères de succès et refusez toute complétion partielle silencieuse.
Le changement de mentalité
Pour l’étape du changement de mentalité, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés. Placez l’état au même endroit que le composant responsable de la mutation ; placer tout dans un stockage global rend les erreurs liées aux temps d’exécution plus difficiles à détecter.
En résumé
Pour l’étape The Bottom Line, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système. Placez l’état avec le composant qui gère la mutation. Mettre tout dans un stockage global rend les erreurs de synchronisation plus difficiles à détecter.
Liste de contrôle opérationnelle
Lorsque vous travaillez sur l’étape de la liste de contrôle opérationnelle, écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste garantit que les modifications ultérieures du code restent transparentes.
Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une seule responsabilité et non un processus embrouillé.
Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.
Fixez les versions des dépendances et enregistrez le digest de l’image utilisée pour la démonstration. La reproductibilité vaut mieux que les connaissances propres à un groupe.
Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définez des vérifications de succès, et refusez toute complétion partielle silencieuse.
Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.
Au préalable de promouvoir l’ensemble des composants, figez les versions, conservez une transcription exemplaire pour le chemin critique, et vérifiez les étapes de réversion. Les environnements partagés nécessitent des limites de fréquence d’accès, des contrôles de location, ainsi qu’un responsable clair pour la rotation des secrets. Préférez une fiabilité solide à des démonstrations brillantes mais ponctuelles.
Note pour le lot d6a7f4e83dda : gardez les clés du fournisseur en dehors du répertoire, fixez un plafond pour les tokens par session, et stockez les transcriptions à côté des fichiers de configuration d’évaluation afin que les remplacements ultérieurs de modèles restent comparables.