prerender¶
prerender рендерит дерево React в строку статического HTML с помощью Web Stream.
1 | |
Примечание
Этот API зависит от Web Streams. Для Node.js используйте prerenderToNodeStream.
Описание¶
prerender(reactNode, options?)¶
Вызовите prerender, чтобы отрендерить приложение в статический HTML.
1 2 3 4 5 6 7 8 9 10 | |
На клиенте вызовите hydrateRoot, чтобы сделать сгенерированный сервером HTML интерактивным.
Параметры¶
reactNode: Узел React, который вы хотите отрендерить в HTML. Например, JSX-узел<App />. Ожидается, что он представляет весь документ, поэтому компонент App должен вывести тег<html>.- опционально
options: Объект с опциями статической генерации.- опционально
bootstrapScriptContent: Если указано, эта строка будет помещена в инлайн-тег<script>. - опционально
bootstrapScripts: Массив URL-строк для тегов<script>, которые будут выведены на странице. Используйте его, чтобы включить<script>, вызывающийhydrateRoot. Опустите его, если вы вообще не хотите запускать React на клиенте. - опционально
bootstrapModules: АналогичноbootstrapScripts, но вместо этого выводится<script type="module">. - опционально
identifierPrefix: Строковый префикс, который React использует для идентификаторов, генерируемыхuseId. Полезен, чтобы избежать конфликтов при использовании нескольких корней на одной странице. Должен совпадать с префиксом, переданным вhydrateRoot. - опционально
importMap: Объект карты импорта со свойствамиimportsиscopes. React выводит его как инлайн-тег<script type="importmap">перед любыми модульными скриптами, чтобы теги<script type="module">(например, изbootstrapModules) могли использовать спецификаторы модулей без пути. - опционально
maxHeadersLength: Максимальная суммарная длина содержимого заголовка, передаваемого вonHeaders, в единицах кода UTF-16. По умолчанию 2000. Когда предел достигнут, React перестаёт добавлять подсказки о ресурсах в заголовки. - опционально
namespaceURI: Строка с корневым namespace URI для потока. По умолчанию используется обычный HTML. Передайте'http://www.w3.org/2000/svg'для SVG или'http://www.w3.org/1998/Math/MathML'для MathML. - опционально
onBrowserBailout: Обратный вызов, который React вызывает, когда восстанавливается послеbrowser(), оставляя фолбэк Suspense, который браузер заменит. Он получаетError, описывающий рендеринг только в браузере, и объектerrorInfo, содержащийcomponentStack. Если вbrowserбыла передана причина, она доступна какerror.cause. По умолчанию React ничего не делает. Как сообщать о рендеринге только в браузере. - опционально
onError: Обратный вызов, который срабатывает при любой серверной ошибке, восстановимой или нет. По умолчанию он только вызываетconsole.error. Если вы переопределяете его, чтобы записывать отчёты о сбоях, всё равно вызывайтеconsole.error. Его также можно использовать, чтобы изменить код состояния до того, как будет выдана оболочка. - опционально
onHeaders: Обратный вызов, который срабатывает, когда React определил подсказки о ресурсах документа, такие как preconnect и предварительная загрузка таблиц стилей, шрифтов или изображений с высоким приоритетом. Он получает экземплярHeadersс соответствующим значением заголовкаLink, чтобы вы могли отправить его как HTTP-заголовок ответа или как ответ 103 Early Hints. React вызывает его даже когда подсказок о ресурсах нет. Содержимое заголовка ограниченоmaxHeadersLength. - опционально
progressiveChunkSize: Количество байт в чанке. Подробнее об эвристике по умолчанию. - опционально
signal: Сигнал прерывания, который позволяет прервать пререндер и дорендерить остальное на клиенте.
- опционально
Возвращаемое значение¶
prerender возвращает промис:
- Если рендеринг прошёл успешно, промис разрешится в объект, содержащий:
prelude: веб-поток HTML. Этот поток можно использовать, чтобы отправлять ответ частями, или прочитать весь поток в строку.postponed: непрозрачный объект, сериализуемый в JSON, который можно передать вresume, еслиprerenderне завершился. Иначеnull: это значит, чтоpreludeсодержит всё содержимое и продолжение не нужно.
- Если рендеринг не удался, промис будет отклонён. Используйте это, чтобы вывести резервную оболочку.
Предупреждения¶
nonce недоступен при пререндере. Nonce должен быть уникальным для каждого запроса, и если вы защищаете приложение с помощью CSP, включать значение nonce в сам пререндер было бы неуместно и небезопасно.
Когда использовать prerender?
Статический API prerender используется для статической генерации на сервере (SSG). В отличие от renderToString, prerender ждёт загрузки всех данных, прежде чем разрешиться. Поэтому он подходит для генерации статического HTML целой страницы, включая данные, которые нужно получить с помощью Suspense. Чтобы передавать содержимое потоком по мере загрузки, используйте потоковый API серверного рендеринга (SSR), например renderToReadableStream.
prerender можно прервать и позже либо продолжить с помощью resumeAndPrerender, либо возобновить с помощью resume, чтобы поддержать частичный пререндер.
Использование¶
Рендеринг дерева React в поток статического HTML¶
Вызовите prerender, чтобы отрендерить дерево React в статический HTML в читаемый веб-поток:
1 2 3 4 5 6 7 8 9 10 | |
Наряду с корневым компонентом нужно передать список путей к bootstrap-тегам <script>. Корневой компонент должен возвращать весь документ, включая корневой тег <html>.
Например, он может выглядеть так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
React внедрит doctype и ваши bootstrap-теги <script> в результирующий поток HTML:
1 2 3 4 5 | |
На клиенте bootstrap-скрипт должен гидратировать весь document вызовом hydrateRoot:
1 2 3 4 | |
Это прикрепит обработчики событий к статическому HTML, сгенерированному сервером, и сделает его интерактивным.
Чтение путей CSS и JS активов из выходных данных сборки
Итоговые URL активов (например, файлов JavaScript и CSS) часто хешируются после сборки. Например, вместо styles.css может получиться styles.123456.css. Хеширование имён файлов статических активов гарантирует, что каждая отдельная сборка одного и того же актива получит другое имя файла. Это полезно, потому что позволяет безопасно включить долгосрочное кэширование статических активов: файл с определённым именем никогда не изменит содержимое.
Однако, если URL активов неизвестны до окончания сборки, поместить их в исходный код нельзя. Например, жёстко заданный в JSX путь "/styles.css", как выше, не сработает. Чтобы не держать их в исходном коде, корневой компонент может читать настоящие имена файлов из карты, переданной пропсом:
1 2 3 4 5 6 7 8 9 10 11 | |
На сервере отрендерьте <App assetMap={assetMap} /> и передайте assetMap с URL активов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Поскольку сервер теперь рендерит <App assetMap={assetMap} />, на клиенте его тоже нужно рендерить с assetMap, чтобы не было ошибок гидратации. assetMap можно сериализовать и передать клиенту так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
В примере выше опция bootstrapScriptContent добавляет дополнительный инлайн-тег <script>, который задаёт на клиенте глобальную переменную window.assetMap. Так клиентский код читает тот же assetMap:
1 2 3 4 | |
И клиент, и сервер рендерят App с одним и тем же пропсом assetMap, поэтому ошибок гидратации нет.
Рендеринг дерева React в строку статического HTML¶
Вызовите prerender, чтобы отрендерить приложение в строку статического HTML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Так вы получите первоначальный неинтерактивный HTML-вывод компонентов React. На клиенте нужно вызвать hydrateRoot, чтобы гидратировать этот сгенерированный сервером HTML и сделать его интерактивным.
Ожидание загрузки всех данных¶
prerender ждёт загрузки всех данных, прежде чем закончить генерацию статического HTML и разрешиться. Например, рассмотрим страницу профиля с обложкой, боковой панелью с друзьями и фотографиями и списком записей:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Представьте, что <Posts /> нужно загрузить данные, и это занимает время. В идеале стоит дождаться записей, чтобы они попали в HTML. Для этого можно использовать Suspense и приостановиться на данных: prerender дождётся завершения приостановленного содержимого, прежде чем разрешиться в статический HTML.
Примечание
Приостанавливаются только данные, прочитанные из источника, который активирует границу Suspense, например промис, прочитанный через use. Suspense не замечает данные, полученные внутри Эффекта или обработчика события.
Прерывание пререндера¶
Пререндер можно заставить «сдаться» после таймаута:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Любые границы Suspense с незавершёнными дочерними элементами попадут в prelude в состоянии фолбэка.
Это можно использовать для частичного пререндера вместе с resume или resumeAndPrerender.
Устранение неполадок¶
Поток не начинается, пока не отрендерится всё приложение¶
Ответ prerender ждёт, пока отрендерится всё приложение, включая разрешение всех границ Suspense, и только потом разрешается. Он предназначен для статической генерации сайта (SSG) заранее и не поддерживает потоковую передачу содержимого по мере загрузки.
Чтобы передавать содержимое потоком по мере загрузки, используйте потоковый API серверного рендеринга, например renderToReadableStream.
Источник — https://react.dev/reference/react-dom/static/prerender