TGViewer
SuperOleg dev notes SuperOleg dev notes @super_oleg_dev · 1.75K subscribers
Post #133 1.6K
Теперь фреймворк умеет в потоковый рендеринг, появились deferred экшены, и Await компонент для использования этих экшенов вместе с Suspense.

Большая часть работы сделана, проблемы как всегда в деталях.

Тут очередная хвала React Working Group, а именно гайду по миграции для авторов библиотек - https://github.com/reactwg/react-18/discussions/114 - этот гайд так или иначе затрагивает все проблемы с которыми я столкнулся.

Первое, tramvai использует defer скрипты в head теге - в обычном случае как мне кажется они имеют все преимущества перед async скриптами.

Но у нас потоковый рендер, и полная загрузка страницы откладывается до завершения стрима - это значит что и defer скрипты не будут выполнены до этого момента!
А это полностью ломает преимущества Selective Hydration - новое API hydrateRoot умеет гидрировать полученную разметку по частям, по мере поступления в потоке.

Стриминговый рендеринг я уже закрыл за флагом, за этим же флагом изменил добавление скриптов с параметром async вместо defer.

Следующее, мы не можем запускать гидрацию до того как Реакт отдал application shell, то есть если наши скрипты будут выполнены и запустят гидрацию пока <APP /> пустой, очевидно получим ошибку.

Это решается с помощью bootstrapScriptContent / bootstrapScripts опций у метода renderToPipeableStream, код для инициализации гидрации будет добавлен ровно в тот момент, когда на клиент передали основную часть разметки и можем начать гидрацию.

Далее, у нас могут быть lazy компоненты (loadable) внутри Suspense и Await.

Для корректной гидрации этих компонентов, их JS и CSS файлы надо инжектить в стрим, и делать это до инжекта разметки соответствующих компонентов, и эти ресурсы должны быть загружены блокирующим браузер образом.
CSS через link и так загружается синхронно, JS скрипт должен также быть загружен синхронно, без async или defer атрибутов.
В принципе с помощью ChunkExtractor от loadable это решается без проблем, главное не задублировать уже отправленные ассеты. Добавил эту логику в стрим HtmlWritable из пары постов выше.

Итоговый HTML для наглядности в отдельном посте.

Также еще нужно учесть SPA-переходы, сериализацию объекта Error, дедупликацию работы с Deferred объектами и другие небольшие нюансы.
GitHub Library Upgrade Guide: <script> (e.g. SSR frameworks) · reactwg react-18 · Discussion #114 Library Upgrade Guide: <script> This is an upgrade guide for frameworks and custom app setups that manages loading JS modules and inserting script tags. In particular if they work to support ...
  • 🔥 7
  • 👍 2
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 →