From bafd3775dac8d6850ba3509752cec8246c3326ac Mon Sep 17 00:00:00 2001 From: "translate-react-bot[bot]" <251169733+translate-react-bot[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:12:11 +0000 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20translate=20`prerenderToNodeStream.?= =?UTF-8?q?md`=20to=20=D0=A0=D1=83=D1=81=D1=81=D0=BA=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../react-dom/static/prerenderToNodeStream.md | 139 +++++++++--------- 1 file changed, 69 insertions(+), 70 deletions(-) diff --git a/src/content/reference/react-dom/static/prerenderToNodeStream.md b/src/content/reference/react-dom/static/prerenderToNodeStream.md index fb8073ef07..7e56340a0a 100644 --- a/src/content/reference/react-dom/static/prerenderToNodeStream.md +++ b/src/content/reference/react-dom/static/prerenderToNodeStream.md @@ -4,7 +4,7 @@ title: prerenderToNodeStream -`prerenderToNodeStream` renders a React tree to a static HTML string using a [Node.js Stream.](https://nodejs.org/api/stream.html). +`prerenderToNodeStream` рендерит React-дерево в статический HTML-строку с использованием [Node.js Stream.](https://nodejs.org/api/stream.html). ```js const {prelude} = await prerenderToNodeStream(reactNode, options?) @@ -16,22 +16,22 @@ const {prelude} = await prerenderToNodeStream(reactNode, options?) -This API is specific to Node.js. Environments with [Web Streams,](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) like Deno and modern edge runtimes, should use [`prerender`](/reference/react-dom/static/prerender) instead. +Этот API специфичен для Node.js. В средах с [Web Streams,](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) таких как Deno и современные серверные среды выполнения (edge runtimes), следует использовать [`prerender`](/reference/react-dom/static/prerender) вместо этого. --- -## Reference {/*reference*/} +## Справочник {/*reference*/} ### `prerenderToNodeStream(reactNode, options?)` {/*prerender*/} -Call `prerenderToNodeStream` to render your app to static HTML. +Вызовите `prerenderToNodeStream` для рендеринга вашего приложения в статический HTML. ```js import { prerenderToNodeStream } from 'react-dom/static'; -// The route handler syntax depends on your backend framework +// Синтаксис обработчика маршрута зависит от вашего серверного фреймворка app.use('/', async (request, response) => { const { prelude } = await prerenderToNodeStream(, { bootstrapScripts: ['/main.js'], @@ -42,55 +42,55 @@ app.use('/', async (request, response) => { }); ``` -On the client, call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) to make the server-generated HTML interactive. +На клиенте вызовите [`hydrateRoot`](/reference/react-dom/client/hydrateRoot), чтобы сделать сгенерированный сервером HTML интерактивным. -[See more examples below.](#usage) +[См. больше примеров ниже.](#usage) -#### Parameters {/*parameters*/} +#### Параметры {/*parameters*/} -* `reactNode`: A React node you want to render to HTML. For example, a JSX node like ``. It is expected to represent the entire document, so the App component should render the `` tag. +* `reactNode`: React-узел, который вы хотите отрендерить в HTML. Например, JSX-узел вроде ``. Ожидается, что он будет представлять весь документ, поэтому компонент App должен рендерить тег ``. -* **optional** `options`: An object with static generation options. - * **optional** `bootstrapScriptContent`: If specified, this string will be placed in an inline ` ``` -On the client, your bootstrap script should [hydrate the entire `document` with a call to `hydrateRoot`:](/reference/react-dom/client/hydrateRoot#hydrating-an-entire-document) +На клиенте ваш bootstrap-скрипт должен [гидрировать весь `document` вызовом `hydrateRoot`:](/reference/react-dom/client/hydrateRoot#hydrating-an-entire-document) ```js [[1, 4, ""]] import { hydrateRoot } from 'react-dom/client'; @@ -142,15 +142,15 @@ import App from './App.js'; hydrateRoot(document, ); ``` -This will attach event listeners to the static server-generated HTML and make it interactive. +Это прикрепит обработчики событий к статическому HTML, сгенерированному сервером, и сделает его интерактивным. -#### Reading CSS and JS asset paths from the build output {/*reading-css-and-js-asset-paths-from-the-build-output*/} +#### Чтение путей к CSS и JS ресурсам из вывода сборки {/*reading-css-and-js-asset-paths-from-the-build-output*/} -The final asset URLs (like JavaScript and CSS files) are often hashed after the build. For example, instead of `styles.css` you might end up with `styles.123456.css`. Hashing static asset filenames guarantees that every distinct build of the same asset will have a different filename. This is useful because it lets you safely enable long-term caching for static assets: a file with a certain name would never change content. +Окончательные URL-адреса ресурсов (таких как файлы JavaScript и CSS) часто хешируются после сборки. Например, вместо `styles.css` вы можете получить `styles.123456.css`. Хеширование имён файлов статических ресурсов гарантирует, что каждая отдельная сборка одного и того же ресурса будет иметь другое имя файла. Это полезно, поскольку позволяет безопасно включить долгосрочное кеширование для статических ресурсов: файл с определённым именем никогда не изменит своё содержимое. -However, if you don't know the asset URLs until after the build, there's no way for you to put them in the source code. For example, hardcoding `"/styles.css"` into JSX like earlier wouldn't work. To keep them out of your source code, your root component can read the real filenames from a map passed as a prop: +Однако, если вы не знаете URL-адреса ресурсов до завершения сборки, вы не сможете вставить их в исходный код. Например, жёсткое кодирование `"/styles.css"` в JSX, как было показано ранее, не сработает. Чтобы исключить их из вашего исходного кода, ваш корневой компонент может считывать реальные имена файлов из карты, передаваемой в качестве пропса: ```js {1,6} export default function App({ assetMap }) { @@ -166,10 +166,10 @@ export default function App({ assetMap }) { } ``` -On the server, render `` and pass your `assetMap` with the asset URLs: +На сервере рендерите `` и передайте вашу `assetMap` с URL-адресами ресурсов: ```js {1-5,8,9} -// You'd need to get this JSON from your build tooling, e.g. read it from the build output. +// Вам нужно будет получить этот JSON из ваших инструментов сборки, например, прочитать его из вывода сборки. const assetMap = { 'styles.css': '/styles.123456.css', 'main.js': '/main.123456.js' @@ -185,10 +185,10 @@ app.use('/', async (request, response) => { }); ``` -Since your server is now rendering ``, you need to render it with `assetMap` on the client too to avoid hydration errors. You can serialize and pass `assetMap` to the client like this: +Поскольку ваш сервер теперь рендерит ``, вам нужно рендерить его и на клиенте с `assetMap`, чтобы избежать ошибок гидратации. Вы можете сериализовать и передать `assetMap` клиенту следующим образом: ```js {9-10} -// You'd need to get this JSON from your build tooling. +// Вам нужно будет получить этот JSON из ваших инструментов сборки. const assetMap = { 'styles.css': '/styles.123456.css', 'main.js': '/main.123456.js' @@ -196,7 +196,7 @@ const assetMap = { app.use('/', async (request, response) => { const { prelude } = await prerenderToNodeStream(, { - // Careful: It's safe to stringify() this because this data isn't user-generated. + // Осторожно: безопасно использовать stringify() это, потому что эти данные не генерируются пользователем. bootstrapScriptContent: `window.assetMap = ${JSON.stringify(assetMap)};`, bootstrapScripts: [assetMap['/main.js']], }); @@ -206,7 +206,7 @@ app.use('/', async (request, response) => { }); ``` -In the example above, the `bootstrapScriptContent` option adds an extra inline ` ``` -На клиенте ваш bootstrap-скрипт должен [гидрировать весь `document` вызовом `hydrateRoot`:](/reference/react-dom/client/hydrateRoot#hydrating-an-entire-document) +На клиенте ваш скрипт инициализации должен [гидрировать весь `document` вызовом `hydrateRoot`:](/reference/react-dom/client/hydrateRoot#hydrating-an-entire-document) ```js [[1, 4, ""]] import { hydrateRoot } from 'react-dom/client'; @@ -146,11 +145,11 @@ hydrateRoot(document, ); -#### Чтение путей к CSS и JS ресурсам из вывода сборки {/*reading-css-and-js-asset-paths-from-the-build-output*/} +#### Чтение путей к CSS и JS файлам из вывода сборки {/*reading-css-and-js-asset-paths-from-the-build-output*/} -Окончательные URL-адреса ресурсов (таких как файлы JavaScript и CSS) часто хешируются после сборки. Например, вместо `styles.css` вы можете получить `styles.123456.css`. Хеширование имён файлов статических ресурсов гарантирует, что каждая отдельная сборка одного и того же ресурса будет иметь другое имя файла. Это полезно, поскольку позволяет безопасно включить долгосрочное кеширование для статических ресурсов: файл с определённым именем никогда не изменит своё содержимое. +Окончательные URL-адреса ресурсов (таких как файлы JavaScript и CSS) часто хешируются после сборки. Например, вместо `styles.css` вы можете получить `styles.123456.css`. Хеширование имён файлов статических ресурсов гарантирует, что каждая отдельная сборка одного и того же ресурса будет иметь другое имя файла. Это полезно, потому что позволяет безопасно включить долгосрочное кеширование для статических ресурсов: файл с определённым именем никогда не изменит своего содержимого. -Однако, если вы не знаете URL-адреса ресурсов до завершения сборки, вы не сможете вставить их в исходный код. Например, жёсткое кодирование `"/styles.css"` в JSX, как было показано ранее, не сработает. Чтобы исключить их из вашего исходного кода, ваш корневой компонент может считывать реальные имена файлов из карты, передаваемой в качестве пропса: +Однако, если вы не знаете URL-адреса ресурсов до завершения сборки, вы не сможете указать их в исходном коде. Например, жёсткое кодирование `"/styles.css"` в JSX, как было показано ранее, не сработает. Чтобы исключить их из вашего исходного кода, ваш корневой компонент может считывать реальные имена файлов из карты, передаваемой в качестве пропса: ```js {1,6} export default function App({ assetMap }) { @@ -166,7 +165,7 @@ export default function App({ assetMap }) { } ``` -На сервере рендерите `` и передайте вашу `assetMap` с URL-адресами ресурсов: +На сервере рендерите `` и передавайте вашу `assetMap` с URL-адресами ресурсов: ```js {1-5,8,9} // Вам нужно будет получить этот JSON из ваших инструментов сборки, например, прочитать его из вывода сборки. @@ -185,7 +184,7 @@ app.use('/', async (request, response) => { }); ``` -Поскольку ваш сервер теперь рендерит ``, вам нужно рендерить его и на клиенте с `assetMap`, чтобы избежать ошибок гидратации. Вы можете сериализовать и передать `assetMap` клиенту следующим образом: +Поскольку ваш сервер теперь рендерит ``, вам также нужно будет рендерить его с `assetMap` на клиенте, чтобы избежать ошибок гидратации. Вы можете сериализовать и передать `assetMap` клиенту следующим образом: ```js {9-10} // Вам нужно будет получить этот JSON из ваших инструментов сборки. @@ -221,7 +220,7 @@ hydrateRoot(document, ); --- -### Рендеринг React-дерева в строку статического HTML {/*rendering-a-react-tree-to-a-string-of-static-html*/} +### Рендеринг дерева React в строку статического HTML {/*rendering-a-react-tree-to-a-string-of-static-html*/} Вызовите `prerenderToNodeStream` для рендеринга вашего приложения в строку статического HTML: @@ -244,13 +243,13 @@ async function renderToString() { } ``` -Это создаст первоначальный неинтерактивный HTML-вывод ваших React-компонентов. На клиенте вам нужно будет вызвать [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) для *гидратации* этого сгенерированного сервером HTML и его интерактивности. +Это создаст начальный неинтерактивный HTML-вывод ваших компонентов React. На клиенте вам нужно будет вызвать [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) для *гидратации* этого сгенерированного сервером HTML и сделать его интерактивным. --- ### Ожидание загрузки всех данных {/*waiting-for-all-data-to-load*/} -`prerenderToNodeStream` ждёт загрузки всех данных перед завершением генерации статического HTML и разрешением. Например, рассмотрим страницу профиля, которая отображает обложку, боковую панель с друзьями и фотографиями, а также список постов: +`prerenderToNodeStream` ждет загрузки всех данных перед завершением генерации статического HTML и разрешением. Например, рассмотрим страницу профиля, которая отображает обложку, боковую панель с друзьями и фотографиями, а также список постов: ```js function ProfilePage() { @@ -269,7 +268,7 @@ function ProfilePage() { } ``` -Представьте, что `` нужно загрузить некоторые данные, что занимает некоторое время. В идеале вы бы хотели дождаться завершения загрузки постов, чтобы они были включены в HTML. Для этого вы можете использовать Suspense для приостановки загрузки данных, и `prerenderToNodeStream` будет ждать завершения приостановленного контента перед разрешением в статический HTML. +Представьте, что `` нужно загрузить некоторые данные, что занимает некоторое время. В идеале вы хотите дождаться завершения загрузки постов, чтобы они были включены в HTML. Для этого вы можете использовать Suspense для приостановки загрузки данных, и `prerenderToNodeStream` будет ждать завершения приостановленного контента перед разрешением в статический HTML. @@ -281,7 +280,7 @@ function ProfilePage() { Suspense **не** обнаруживает, когда данные загружаются внутри Effect или обработчика событий. -Точный способ загрузки данных в компоненте `Posts` выше зависит от вашего фреймворка. Если вы используете фреймворк, поддерживающий Suspense, вы найдёте подробности в его документации по получению данных. +Точный способ загрузки данных в компоненте `Posts` выше зависит от вашего фреймворка. Если вы используете фреймворк, поддерживающий Suspense, вы найдете подробности в его документации по получению данных. Получение данных с поддержкой Suspense без использования структурированного фреймворка пока не поддерживается. Требования к реализации источника данных с поддержкой Suspense нестабильны и не документированы. Официальный API для интеграции источников данных с Suspense будет выпущен в будущей версии React. @@ -291,7 +290,7 @@ Suspense **не** обнаруживает, когда данные загруж ### Отмена предварительного рендеринга {/*aborting-prerendering*/} -Вы можете заставить предварительный рендеринг "сдаться" по истечении времени ожидания: +Вы можете заставить предварительный рендеринг "сдаться" после истечения времени ожидания: ```js {2-5,11} async function renderToString() { @@ -302,21 +301,21 @@ async function renderToString() { try { // prelude будет содержать весь HTML, который был предварительно отрендерен - // до того, как контроллер отменил операцию. + // до того, как контроллер был отменен. const {prelude} = await prerenderToNodeStream(, { signal: controller.signal, }); //... ``` -Любые границы Suspense с незавершёнными дочерними элементами будут включены в prelude в состоянии ожидания (fallback state). +Любые границы Suspense с незавершенными дочерними элементами будут включены в prelude в состоянии отложенного отображения (fallback state). --- ## Устранение неполадок {/*troubleshooting*/} -### Мой поток не начинается до тех пор, пока всё приложение не будет отрендерено {/*my-stream-doesnt-start-until-the-entire-app-is-rendered*/} +### Мой поток не начинается, пока всё приложение не будет отрендерено {/*my-stream-doesnt-start-until-the-entire-app-is-rendered*/} -Ответ `prerenderToNodeStream` ждёт завершения рендеринга всего приложения, включая ожидание разрешения всех границ Suspense, перед разрешением. Он предназначен для статической генерации сайтов (SSG) заранее и не поддерживает потоковую передачу большего контента по мере его загрузки. +Ответ `prerenderToNodeStream` ждет завершения рендеринга всего приложения, включая ожидание разрешения всех границ Suspense, перед разрешением. Он предназначен для статической генерации сайта (SSG) заранее и не поддерживает потоковую передачу большего контента по мере его загрузки. -Для потоковой передачи контента по мере его загрузки используйте API потоковой серверной рендеринга, такой как [renderToPipeableStream](/reference/react-dom/server/renderToPipeableStream). \ No newline at end of file +Для потоковой передачи контента по мере его загрузки используйте API потоковой передачи серверного рендеринга, такой как [renderToPipeableStream](/reference/react-dom/server/renderToPipeableStream). \ No newline at end of file