Acelerando a análise de JSON grande
Resumo: Otimizar na ordem errada torna inútil toda troca de biblioteca. Meça rede, análise e renderização separadamente, depois reduza análises, encolha payloads e faça streaming.

Resumo da ópera: meça rede, análise e renderização separadamente primeiro — a maioria dos "análise lenta" acaba sendo renderização lenta — depois suba a escada em ordem: menos análises, payloads menores, streaming, um worker e, por último, um formato binário.
Não comece trocando bibliotecas. Adicione um cronômetro e você normalmente descobrirá que a renderização é o problema.
Passo um: meça as etapas
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();
| Etapa dominante | Problema real | Correção |
|---|---|---|
| Rede | Payload grande demais | Seleção de campos, paginação, compressão |
JSON.parse |
Entrada realmente grande | Menos análises, streaming, worker |
| Renderização | Dezenas de milhares de nós de uma vez | Lista virtual, paginação, recolhimento |
Navegadores modernos analisam 1MB em cerca de 5–15ms e 10MB em 80–150ms. Se 10MB leva dois segundos, JSON.parse não é o seu gargalo.
Passo dois: analise menos
O ganho mais barato, e o mais negligenciado.
- Pare de analisar o mesmo payload repetidamente. Dez componentes, cada um chamando
JSON.parse(localStorage.getItem(...)), são dez análises. Faça cache uma vez no nível de módulo. - Pare de usar
JSON.parse(JSON.stringify(x))para cópias profundas. Isso custa mais que o dobro do volume de dados;structuredClonenão. - Não analise na thread principal e depois envie o objeto para um worker.
postMessageo clona de novo. Envie o texto cru e deixe o worker analisar. - Peça menos campos. Se a interface precisa de três propriedades, a API não deveria enviar trezentas.
Passo três: encolha o payload
Paginação por page/size, cursores em vez de offset profundo, campos de resumo em endpoints de lista. Isso normalmente supera toda otimização de frontend combinada, porque reduz rede, análise e memória de uma vez.
Passo quatro: faça streaming
Quando os dados precisam ser processados como um todo e realmente são grandes:
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);
}
Mais código, e sem acesso aleatório — só adequado para processamento registro por registro.
Passo cinco: tire da thread principal
Analisar é rápido, mas bloqueante. Coloque em um worker e passe o texto, não o objeto analisado, ou a clonagem estruturada dobra o custo.
Passo seis: mude o formato, por último
Para tráfego interno consistentemente na casa das dezenas de megabytes, o NDJSON faz streaming naturalmente, e Protobuf ou MessagePack são menores e mais rápidos. Ambos são mudanças de protocolo que exigem coordenação.
Não faça
evalde JSON: inseguro e não é mais rápido- Serializar JSON para embuti-lo em JSON: dobra o tamanho
- Analisar centenas de milhares de strings minúsculas em um laço: agrupe-as
Perguntas frequentes
Como sei se o gargalo é a análise ou a renderização?
Cronometre a requisição, a leitura do texto, o JSON.parse e a renderização separadamente com performance.now(), e trate a maior etapa como o gargalo real. Navegadores modernos analisam 1MB em cerca de 5–15ms e 10MB em 80–150ms, então um payload de 10MB que leva dois segundos raramente é um problema de JSON.parse.
Por que trocar de biblioteca normalmente não ajuda?
JSON.parse já é nativo e rápido; a maior parte dos "análise lenta" vem de análise repetida ou de renderizar dezenas de milhares de nós de uma vez. Trocar de biblioteca rende 10–30%, enquanto remover uma análise completa muitas vezes economiza metade.
Devo mover a análise para um Web Worker?
Mova para um worker quando a análise bloqueia a thread principal e a página congela ou as animações perdem quadros. Passe o texto cru em vez do objeto analisado, caso contrário a clonagem estruturada do postMessage dobra o custo.