Большая часть работы сделана, проблемы как всегда в деталях.
Тут очередная хвала 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 объектами и другие небольшие нюансы.