TGViewer
SuperOleg dev notes SuperOleg dev notes @super_oleg_dev · 1.75K subscribers
Post #128 857
Основная сложность для фреймворка tramvai в реализации этой фичи было полное отсутствие поддержки стриминга HTML разметки.

Эксперименты со стримингом были, но в целом есть ряд минусов, рассмотренных в этом посте - https://t.me/super_oleg_dev/49, из-за которых долго не развивали идею. Но концепция Await + defer очень уж хороша, что бы ее не использовать.

Плюс недавно в твиттере увидел интересную мысль, что если в целом для пользователя есть возможность благодаря стримингу сильно ускорить ответ и улучшить UX, этот пользователь в итоге принесет больше денег и возросшая сложность и нагрузка на сервера того стоит)

Итак, как сейчас работает трамвай что бы отрендерить HTML:

- Есть заранее заданная схема HTML страницы со слотами (например мета-теги, инлайн скрипты, head скрипты, body скрипты и т.д.)
- На разных этапах обработки запроса на эти слоты регистрируются соответствующие ресурсы (допустим сходили в API, добавили нужный title, инлайн-скрипт или json-ld)
- В самом конце, рендерим React компонент через renderToString, и получаем окончательный список ресурсов (до рендера не знаем ссылки на JS/CSS используемых на странице loadable компонентов)
- Склеиваем все по схеме, отдаем ответ клиенту одним чанком

Вот как выглядит флоу генерации HTML:

// тут по дефолту renderToString
renderReact()

// после рендера знаем все JS/CSS которые нужны на странице
addScriptsAndStyles()

// сериализуем данные для передачи на клиент
dehydrateState()

// генерируем HTML по схеме
generateHtml()

И для наглядности, представим схему страницы в очень упрощенном варианте:

<head>
<META />
<LINKS />
<SCRIPTS />
</head>
<body>
<APP />
<TAIL_SCRIPTS />
</body>

Тут <APP /> - это часть разметки которую рендерит React.

При потоковом рендеринге, я решил не ломать полностью существующий флоу ответа, и не начинать стримить раньше, а делать это в том же месте где раньше отдавали всю страницу целиком - тогда мы будем уверены что все необходимые данные уже получены, а ресурсы зарегистрированы, и не нужно будет изобретать свои механизмы чтобы “достримить” различные теги на страницу и к примеру вставить в <head> после того, как уже отдали соответствующий закрывающий тег (пример проблемы)
Telegram SuperOleg dev notes Привет! Активно готовим tramvai к React 18, хочу поделиться важными для меня плюсами, и к сожалению минусами. Рендеринг на сервере стал быстрее. На одном простом демо приложении, RPS вырос с 50 до 70 просто при обновлении react и react-dom. Т.к. именно…
  • 👍 6
  • 🔥 6
More from @super_oleg_dev
  1. Sep 10, 2026Посмотреть на работу анимаций и скролла можно в нашей демке, основанной на примере Remix ф…
  2. Sep 10, 2026Далее, про скролл. В принципе для SPA-приложений это база, если при переходах на разные ст…
  3. Sep 10, 2026Раз уж меня прорвало, вспомню ещё один интересный кейс. Решали примерно в одно время две п…
  4. Sep 10, 2026Вместо тысячи слов, пример работы и сразу разметка, которая долетает в HTML - и наш механи…
  5. Sep 10, 2026Когда-то давно рассказывал про интеграцию стриминга и deferred загрузки данных в Tramvai -…
  6. Sep 7, 2026TIL, небольшой, но интересный кейс! Делал кастомный анализ бандла через Claude, пишет мне…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →