Accelerare il parsing di JSON di grandi dimensioni
In sintesi: Ottimizzare nell'ordine sbagliato rende inutile qualsiasi cambio di libreria. Misura separatamente rete, parsing e rendering, poi riduci i parsing, comprimi i payload e usa lo streaming.

In sintesi: misura prima separatamente rete, parsing e rendering — la maggior parte del "parsing lento" si rivela rendering lento — poi sali la scala in ordine: meno parsing, payload più piccoli, streaming, un worker e un formato binario per ultimo.
Non iniziare cambiando librerie. Aggiungi un timer e di solito scoprirai che il problema è il rendering.
Passo uno: misurare le fasi
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();
| Fase dominante | Problema reale | Correzione |
|---|---|---|
| Rete | Payload troppo grande | Selezione dei campi, paginazione, compressione |
JSON.parse |
Input davvero grande | Meno parsing, streaming, worker |
| Rendering | Decine di migliaia di nodi in una volta | Lista virtuale, paginazione, compressione |
I browser moderni analizzano 1 MB in circa 5–15 ms e 10 MB in 80–150 ms. Se 10 MB impiegano due secondi, JSON.parse non è il tuo collo di bottiglia.
Passo due: analizzare meno
Il guadagno più economico, e il più trascurato.
- Smetti di analizzare ripetutamente lo stesso payload. Dieci componenti che chiamano ciascuno
JSON.parse(localStorage.getItem(...))sono dieci parsing. Metti in cache una volta a livello di modulo. - Smetti di usare
JSON.parse(JSON.stringify(x))per le copie profonde. Costa più del doppio del volume dei dati;structuredCloneno. - Non analizzare sul thread principale e poi inviare l'oggetto a un worker.
postMessagelo clona di nuovo. Invia il testo grezzo e lascia che il worker lo analizzi. - Chiedi meno campi. Se all'interfaccia servono tre proprietà, l'API non dovrebbe inviarne trecento.
Passo tre: comprimere il payload
Paginazione con page/size, cursori invece di offset profondi, campi riassuntivi negli endpoint di elenco. Questo di solito batte ogni ottimizzazione frontend combinata, perché riduce in una volta rete, parsing e memoria.
Passo quattro: streaming
Quando i dati devono essere elaborati nel loro insieme e sono davvero grandi:
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);
}
Più codice, e nessun accesso casuale — adatto solo all'elaborazione record per record.
Passo cinque: spostarlo fuori dal thread principale
Il parsing è veloce ma bloccante. Mettilo in un worker e passa il testo, non l'oggetto analizzato, altrimenti la clonazione strutturata raddoppia il costo.
Passo sei: cambiare il formato, per ultimo
Per traffico interno che è costantemente nell'ordine di decine di megabyte, NDJSON si presta naturalmente allo streaming, e Protobuf o MessagePack sono più piccoli e veloci. Entrambi sono cambi di protocollo che richiedono coordinamento.
Da non fare
evaldi JSON: non sicuro e non più veloce- Fare
stringifydi JSON per incorporarlo in JSON: raddoppia la dimensione - Analizzare centinaia di migliaia di minuscole stringhe in un ciclo: raggruppale
FAQ
Come capisco se il collo di bottiglia è il parsing o il rendering?
Cronometra separatamente la richiesta, la lettura del testo, JSON.parse e il rendering con performance.now(), e tratta la fase più grande come il collo di bottiglia reale. I browser moderni analizzano 1 MB in circa 5–15 ms e 10 MB in 80–150 ms, quindi un payload da 10 MB che impiega due secondi raramente è un problema di JSON.parse.
Perché cambiare libreria di solito non aiuta?
JSON.parse è già nativo e veloce; la maggior parte del "parsing lento" deriva da parsing ripetuto o dal rendering di decine di migliaia di nodi in una volta. Cambiare libreria compra il 10–30%, mentre rimuovere un parsing completo spesso risparmia metà.
Devo spostare il parsing in un Web Worker?
Spostalo in un worker quando il parsing blocca il thread principale e la pagina si blocca o le animazioni perdono frame. Passa il testo grezzo piuttosto che l'oggetto analizzato, altrimenti la clonazione strutturata di postMessage raddoppia il costo.