Добавить в корзинуПозвонить
Найти в Дзене
Цифровая Переплавка

Progressive JSON: когда данные перестают тормозить интернет

Представьте, что вы открываете страницу, и вместо того, чтобы ждать, пока она загрузится целиком, вы сразу же видите её очертания. Сначала появляется общий каркас, затем постепенно подтягиваются детали — контент, изображения, комментарии. Такая модель уже давно привычна для изображений в формате Progressive JPEG. Но почему бы не применить эту логику и к JSON, основному формату передачи данных в веб-приложениях? Классический подход передачи данных с сервера клиенту прост и прямолинеен: JSON-объект отправляется целиком. Клиент не может начать обработку до тех пор, пока последний байт не прилетит и JSON не будет полностью распарсен. Представьте ситуацию: {
"header": "Добро пожаловать в блог!",
"post": {
"content": "Это моя статья",
"comments": ["Первый комментарий", "Второй комментарий"]
},
"footer": "Надеюсь, вам понравится"
} Даже если заголовок и футер готовы мгновенно, а комментарии грузятся медленно из-за долгого запроса к базе, вам придётся ждать полной загрузки. Каж
Оглавление
Сервер и клиент изображены в виде кубов, между которыми волнообразно проходят многослойные, разноцветные потоки данных-строк. Летающие фигурные скобки символизируют JSON-фрагменты, поступающие параллельно, передавая идею breadth-first загрузки Progressive JSON.
Сервер и клиент изображены в виде кубов, между которыми волнообразно проходят многослойные, разноцветные потоки данных-строк. Летающие фигурные скобки символизируют JSON-фрагменты, поступающие параллельно, передавая идею breadth-first загрузки Progressive JSON.

Представьте, что вы открываете страницу, и вместо того, чтобы ждать, пока она загрузится целиком, вы сразу же видите её очертания. Сначала появляется общий каркас, затем постепенно подтягиваются детали — контент, изображения, комментарии. Такая модель уже давно привычна для изображений в формате Progressive JPEG. Но почему бы не применить эту логику и к JSON, основному формату передачи данных в веб-приложениях?

🐢 JSON: почему медленно — значит привычно?

Классический подход передачи данных с сервера клиенту прост и прямолинеен: JSON-объект отправляется целиком. Клиент не может начать обработку до тех пор, пока последний байт не прилетит и JSON не будет полностью распарсен.

Представьте ситуацию:

{
"header": "Добро пожаловать в блог!",
"post": {
"content": "Это моя статья",
"comments": ["Первый комментарий", "Второй комментарий"]
},
"footer": "Надеюсь, вам понравится"
}

Даже если заголовок и футер готовы мгновенно, а комментарии грузятся медленно из-за долгого запроса к базе, вам придётся ждать полной загрузки. Кажется не слишком рациональным, правда?

🚧 Стриминг — быстрый, но «ломанный»

Решением может стать стриминг JSON, где данные отправляются по частям, и клиент начинает обработку до окончания передачи всего файла. Но и тут не всё гладко:

  • 🧩 JSON может прийти неполным, и у вас просто не будет нужных полей.
  • 🕸️ Неясно, будет ли продолжение у массива или объекта.
  • 🚨 Приложение рискует постоянно обрабатывать «невалидные» данные.

В итоге подход используется редко, только в специфических кейсах, вроде логов или потоковых данных.

🌳 Progressive JSON: потоковая магия с placeholders

Авторы идеи Progressive JSON предлагают принципиально иной подход — передавать JSON не по порядку (depth-first), а слоями (breadth-first). Вместо данных сразу отправляются плейсхолдеры, которые затем постепенно заменяются реальными значениями.

Например, вместо отправки сразу всего объекта:

{
"header": "Добро пожаловать",
"post": "Статья",
"footer": "Футер"
}

Сначала отправляется структура с плейсхолдерами:

jsonCopyEdit{
"header": "$1",
"post": "$2",
"footer": "$3"
}

А затем данные поступают по мере готовности:

/* $1 */
"Добро пожаловать"
/* $3 */
"Футер"
/* $2 */
{
"content": "$4",
"comments": "$5"
}
/* и так далее */

Клиент же заменяет плейсхолдеры на Promises и работает с ними асинхронно, постепенно наполняя структуру:

{
header: "Добро пожаловать",
post: new Promise(), // пока не готово
footer: "Футер"
}

Это значительно ускоряет восприятие данных пользователем и позволяет более интеллектуально управлять загрузкой контента.

💡 Как это работает технически?

За прогрессивной передачей JSON стоят несколько технических особенностей:

  • 🔗 Promises и асинхронность: на клиенте JSON-данные «разворачиваются» через JavaScript-промисы. Это значит, что приложение не блокируется в ожидании всех данных, а загружает контент по мере готовности.
  • 🔄 Гибкое пакетирование: Сервер может группировать данные и отправлять их не обязательно в том порядке, как они были запрошены. Например, медленные комментарии не будут тормозить быструю шапку и подвал страницы.
  • 🔗 Outlining и Dedupe: Progressive JSON позволяет выделять часто используемые объекты в отдельные фрагменты, тем самым снижая повтор данных и экономя трафик.

🎯 Применение на практике: React Server Components

Идея Progressive JSON активно используется в React Server Components (RSC). Благодаря этому React-приложения загружаются намного эффективнее:

  • 🖥️ Скелет интерфейса загружается моментально.
  • Контент и комментарии подгружаются по мере их готовности, плавно раскрываясь для пользователя.
  • 🎨 <Suspense> API позволяет контролировать, как именно появляются данные, обеспечивая приятный пользовательский опыт без скачков интерфейса.

Например, в React можно сделать так, что пользователь сначала увидит заголовок и футер, а комментарии будут отображаться позже, с красивым эффектом загрузки.

📈 А нужно ли всем Progressive JSON?

Конечно, такой подход полезен далеко не всегда. Для простых и небольших JSON-объектов это может быть излишним усложнением. Но Progressive JSON идеален там, где:

  • 🔥 Данные большие и разнородные по времени генерации.
  • 🚄 Интерфейс требует немедленной реакции на любые поступающие данные.
  • 🎯 Критически важна воспринимаемая скорость загрузки контента.

Автор оригинальной статьи Дэн Абрамов предлагает шире взглянуть на эту технологию и использовать её там, где медленные части могут тормозить всё остальное.

Лично я считаю Progressive JSON отличным развитием идеи «интеллектуальной загрузки». В эпоху, когда пользователи нетерпеливы, а приложения перегружены данными, подобные подходы просто необходимы. Важно, чтобы такие инновации становились частью повседневной разработки, улучшая восприятие и скорость современных веб-приложений.

🔗 Оригинальная статья на Overreacted.io