Accélérer le parsing de grands JSON
L’essentiel : Optimiser dans le mauvais ordre rend tout échange de bibliothèque inutile. Mesurez séparément réseau, parsing et rendu, puis réduisez les parsings, diminuez les charges utiles et passez au flux.

L'essentiel : mesurez d'abord séparément réseau, parsing et rendu — la plupart des « parsings lents » se révèlent être des rendus lents — puis gravissez l'échelle dans l'ordre : moins de parsings, charges utiles plus petites, flux, worker, et un format binaire en dernier.
Ne commencez pas par changer de bibliothèque. Ajoutez un chronomètre et vous découvrirez généralement que le rendu est le problème.
Étape un : mesurer les étapes
const t0 = performance.now();
const response = await fetch(url);
const text = await response.text();
const t1 = performance.now();
const data = JSON.parse(text);
const t2 = performance.now();
render(data);
const t3 = performance.now();
| Étape dominante | Vrai problème | Correction |
|---|---|---|
| Réseau | Charge utile trop grande | Sélection de champs, pagination, compression |
JSON.parse |
Entrée réellement volumineuse | Moins de parsings, flux, worker |
| Rendu | Dizaines de milliers de nœuds d'un coup | Liste virtuelle, pagination, repli |
Les navigateurs modernes parsent 1 Mo en environ 5 à 15 ms et 10 Mo en 80 à 150 ms. Si 10 Mo prennent deux secondes, JSON.parse n'est pas votre goulot.
Étape deux : parser moins
Le gain le moins coûteux, et le plus négligé.
- Arrêtez de parser la même charge utile en boucle. Dix composants appelant chacun
JSON.parse(localStorage.getItem(...)), ce sont dix parsings. Mettez en cache une fois au niveau du module. - Arrêtez d'utiliser
JSON.parse(JSON.stringify(x))pour les copies profondes. Cela coûte plus du double du volume de données ;structuredClonenon. - Ne parsez pas sur le thread principal puis n'envoyez pas l'objet à un worker.
postMessagele clone encore. Envoyez le texte brut et laissez le worker parser. - Demandez moins de champs. Si l'interface a besoin de trois propriétés, l'API ne devrait pas en envoyer trois cents.
Étape trois : réduire la charge utile
Pagination par page/size, curseurs au lieu d'offset profond, champs de synthèse dans les points de terminaison de liste. Cela bat généralement toutes les optimisations frontend combinées, car cela réduit à la fois réseau, parsing et mémoire.
Étape quatre : le flux
Quand les données doivent être traitées dans leur ensemble et sont réellement volumineuses :
import { parser } from 'stream-json';
import { streamArray } from 'stream-json/streamers/StreamArray';
const pipeline = fs.createReadStream('big.json').pipe(parser()).pipe(streamArray());
for await (const { value } of pipeline) {
await handleOne(value);
}
Plus de code, et pas d'accès aléatoire — adapté seulement au traitement enregistrement par enregistrement.
Étape cinq : sortir du thread principal
Le parsing est rapide mais bloquant. Mettez-le dans un worker et passez le texte, pas l'objet parsé, sinon le clonage structuré double le coût.
Étape six : changer le format, en dernier
Pour un trafic interne qui fait régulièrement des dizaines de mégaoctets, NDJSON se diffuse naturellement, et Protobuf ou MessagePack sont plus petits et plus rapides. Les deux sont des changements de protocole qui exigent de la coordination.
À ne pas faire
evalsur du JSON : peu sûr et pas plus rapide- Stringifier du JSON pour l'imbriquer dans du JSON : double la taille
- Parser des centaines de milliers de petites chaînes en boucle : lotissez-les
FAQ
Comment savoir si le parsing ou le rendu est le goulot ?
Chronométrez séparément la requête, la lecture du texte, JSON.parse et le rendu avec performance.now(), et traitez l'étape la plus longue comme le vrai goulot. Les navigateurs modernes parsent 1 Mo en environ 5 à 15 ms et 10 Mo en 80 à 150 ms, donc une charge utile de 10 Mo qui prend deux secondes est rarement un problème de JSON.parse.
Pourquoi changer de bibliothèque n'aide-t-il généralement pas ?
JSON.parse est déjà natif et rapide ; la plupart des « parsings lents » viennent de parsings répétés ou du rendu de dizaines de milliers de nœuds d'un coup. Un changement de bibliothèque gagne 10 à 30 %, tandis que supprimer un parsing complet en économise souvent la moitié.
Faut-il déplacer le parsing dans un Web Worker ?
Déplacez-le dans un worker quand le parsing bloque le thread principal et que la page fige ou que les animations perdent des frames. Passez le texte brut plutôt que l'objet parsé, sinon le clonage structuré de postMessage double le coût.