JSON Toolkit

Прискорення розбору великого JSON

Головне: Оптимізація в неправильному порядку робить будь-яку заміну бібліотеки марною. Виміряйте мережу, розбір і відображення окремо, потім скоротіть розбори, зменшіть навантаження й переходьте на потокову обробку.

Середній~5 хв читанняОпубліковано 2026-10-30Оновлено 2026-10-30
Порядок оптимізації розбору великого JSON

Коротко: спершу виміряйте мережу, розбір і відображення окремо — більшість «повільного розбору» виявляється повільним відображенням — потім піднімайтеся драбиною за порядком: менше розборів, менші навантаження, потокова обробка, worker, і двійковий формат останнім.

Не починайте із заміни бібліотек. Додайте один таймер — і зазвичай виявите, що проблема у відображенні.

Крок перший: виміряйте етапи

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();
Домінантний етап Справжня проблема Виправлення
Мережа Навантаження завелике Вибір полів, пагінація, стиснення
JSON.parse Справді великий вхід Менше розборів, потокова обробка, worker
Відображення Десятки тисяч вузлів одразу Віртуальний список, сторінки, згортання

Сучасні браузери розбирають 1 МБ приблизно за 5–15 мс, а 10 МБ — за 80–150 мс. Якщо 10 МБ займає дві секунди, JSON.parse — не ваше вузьке місце.

Крок другий: розбирайте менше

Найдешевший виграш і найбільш проґавлений.

  • Припиніть повторно розбирати те саме навантаження. Десять компонентів, кожен викликає JSON.parse(localStorage.getItem(...)), — це десять розборів. Кешуйте один раз на рівні модуля.
  • Припиніть використовувати JSON.parse(JSON.stringify(x)) для глибоких копій. Це коштує більш ніж удвічі обсяг даних; structuredClone — ні.
  • Не розбирайте на головному потоці й потім не надсилайте обʼєкт у worker. postMessage клонує його знову. Надсилайте сирий текст і дозвольте worker розібрати.
  • Просіть менше полів. Якщо UI потрібні три властивості, API не має надсилати триста.

Крок третій: зменшіть навантаження

Пагінація за page/size, курсори замість глибокого offset, підсумкові поля в кінцевих точках списків. Зазвичай це краще за всі фронтенд-оптимізації разом, бо зменшує мережу, розбір і памʼять одночасно.

Крок четвертий: потокова обробка

Коли дані треба обробити цілком і вони справді великі:

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);
}

Більше коду й без довільного доступу — підходить лише для обробки запис за записом.

Крок пʼятий: перенесіть із головного потоку

Розбір швидкий, але блокуючий. Покладіть його в worker і передавайте текст, а не розібраний обʼєкт, інакше структурне клонування подвоїть ціну.

Крок шостий: змініть формат, останнім

Для внутрішнього трафіку, що стабільно становить десятки мегабайт, NDJSON природно потоковий, а Protobuf чи MessagePack менші й швидші. Обидва — зміни протоколу, що потребують узгодження.

Не робіть

  • eval JSON: небезпечно й не швидше
  • Серіалізувати JSON, щоб вбудувати його в JSON: подвоює розмір
  • Розбирати сотні тисяч крихітних рядків у циклі: пакетуйте їх

Часті питання

Як дізнатися, розбір чи відображення є вузьким місцем?

Зміряйте окремо час запиту, читання тексту, JSON.parse і відображення через performance.now() і вважайте найбільший етап справжнім вузьким місцем. Сучасні браузери розбирають 1 МБ приблизно за 5–15 мс, а 10 МБ — за 80–150 мс, тож навантаження на 10 МБ, що займає дві секунди, рідко є проблемою JSON.parse.

Чому заміна бібліотек зазвичай не допомагає?

JSON.parse уже нативний і швидкий; більшість «повільного розбору» походить із повторного розбору або відображення десятків тисяч вузлів одразу. Заміна бібліотеки купує 10–30%, тоді як видалення одного повного розбору часто дає половину.

Чи переносити розбір у Web Worker?

Переносьте у worker, коли розбір блокує головний потік і сторінка замерзає або анімації втрачають кадри. Передавайте сирий текст, а не розібраний обʼєкт, інакше структурне клонування postMessage подвоїть ціну.

Додаткове читання