prerender は、Webストリームを使用して、Reactツリーを静的HTML文字列にレンダリングします。

const {prelude} = await prerender(reactNode, options?)

注記

このAPIは、Webストリームに依存しています。Node.jsの場合は、代わりにprerenderToNodeStreamを使用してください。


リファレンス

prerender(reactNode, options?)

prerenderを呼び出して、アプリを静的HTMLにレンダリングします。

import { prerender } from 'react-dom/static';

async function handler(request) {
const {prelude} = await prerender(<App />, {
bootstrapScripts: ['/main.js']
});
return new Response(prelude, {
headers: { 'content-type': 'text/html' },
});
}

クライアント側では、hydrateRootを呼び出して、サーバーで生成されたHTMLをインタラクティブにします。

以下の例をご覧ください。

パラメータ

  • reactNode: HTMLにレンダリングするReactノード。たとえば、<App />のようなJSXノード。ドキュメント全体を表すことが想定されているため、Appコンポーネントは<html>タグをレンダリングする必要があります。

  • **オプション** options: 静的生成オプションを含むオブジェクト。

    • **オプション** bootstrapScriptContent: 指定した場合、この文字列はインラインの<script>タグに配置されます。
    • **オプション** bootstrapScripts: ページに出力する<script>タグの文字列URLの配列。これを使用して、hydrateRootを呼び出す<script>を含めます。クライアント側でReactを全く実行したくない場合は、省略します。
    • **オプション** bootstrapModules: bootstrapScriptsと同様ですが、<script type="module">を出力します。
    • **オプション** identifierPrefix: ReactがuseIdによって生成されたIDに使用する文字列プレフィックス。同じページで複数のルートを使用する場合の競合を回避するのに役立ちます。hydrateRootに渡されるのと同じプレフィックスである必要があります。
    • オプション namespaceURI: ストリームのルート名前空間URIを含む文字列。デフォルトは通常のHTMLです。SVGの場合は'http://www.w3.org/2000/svg'、MathMLの場合は'http://www.w3.org/1998/Math/MathML'を渡します。
    • オプション onError: 回復可能回復不可能かに関わらず、サーバーエラーが発生するたびに実行されるコールバック。デフォルトでは、console.errorを呼び出すだけです。クラッシュレポートをログに記録するためにオーバーライドする場合は、必ずconsole.errorも呼び出すようにしてください。また、シェルが出力される前にステータスコードを調整するためにも使用できます。
    • オプション progressiveChunkSize: チャンクのバイト数。デフォルトのヒューリスティックの詳細はこちら。
    • オプション signal: アボートシグナルサーバーレンダリングを中止し、残りをクライアントでレンダリングできます。

戻り値 ...

prerender はPromiseを返します。

注記

prerenderはいつ使うべきですか? ..

静的prerender APIは、静的サーバーサイド生成(SSG)に使用されます。renderToStringとは異なり、prerenderはすべてのデータがロードされるまで待機してから解決します。これにより、Suspenseを使用してフェッチする必要があるデータを含む、ページ全体の静的HTMLの生成に適しています。コンテンツがロードされるにつれてストリーミングするには、renderToReadableStreamのようなストリーミングサーバーサイドレンダリング(SSR)APIを使用します。


使用方法 ...

Reactツリーを静的HTMLのストリームにレンダリングする ...

prerenderを呼び出して、Reactツリーを静的HTMLにレンダリングし、Readable Webストリームに書き込みます。

import { prerender } from 'react-dom/static';

async function handler(request) {
const {prelude} = await prerender(<App />, {
bootstrapScripts: ['/main.js']
});
return new Response(prelude, {
headers: { 'content-type': 'text/html' },
});
}

ルートコンポーネントとともに、ブートストラップ<script>のパスのリストを提供する必要があります。ルートコンポーネントは、ルート<html>タグを含むドキュメント全体を返す必要があります。

例えば、次のようになります。

export default function App() {
return (
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/styles.css"></link>
<title>My app</title>
</head>
<body>
<Router />
</body>
</html>
);
}

ReactはDOCTYPEブートストラップ<script>タグを結果のHTMLストリームに挿入します。

<!DOCTYPE html>
<html>
<!-- ... HTML from your components ... -->
</html>
<script src="/main.js" async=""></script>

クライアント側では、ブートストラップスクリプトはhydrateRootを呼び出してドキュメント全体をハイドレートする必要があります。

import { hydrateRoot } from 'react-dom/client';
import App from './App.js';

hydrateRoot(document, <App />);

これにより、静的にサーバー生成されたHTMLにイベントリスナーがアタッチされ、インタラクティブになります。

詳細

ビルド出力から CSS および JS アセットパスを読み取る

最終的なアセット URL(JavaScript や CSS ファイルなど)は、ビルド後にハッシュ化されることがよくあります。たとえば、`styles.css` の代わりに `styles.123456.css` のようなファイル名になります。静的アセットのファイル名をハッシュ化することで、同じアセットの異なるビルドごとに異なるファイル名が保証されます。これは、静的アセットの長期キャッシュを安全に有効にできるため便利です。特定の名前のファイルの内容が変更されることはありません。

ただし、ビルド後までアセット URL がわからない場合、ソースコードにそれらを配置する方法がありません。たとえば、前述のように JSX に `"/styles.css"` をハードコーディングしても機能しません。ソースコードからそれらを分離するために、ルートコンポーネントは小道具として渡されたマップから実際のファイル名を読み取ることができます。

export default function App({ assetMap }) {
return (
<html>
<head>
<title>My app</title>
<link rel="stylesheet" href={assetMap['styles.css']}></link>
</head>
...
</html>
);
}

サーバー上で、`` をレンダリングし、アセット URL を含む `assetMap` を渡します。

// You'd need to get this JSON from your build tooling, e.g. read it from the build output.
const assetMap = {
'styles.css': '/styles.123456.css',
'main.js': '/main.123456.js'
};

async function handler(request) {
const {prelude} = await prerender(<App assetMap={assetMap} />, {
bootstrapScripts: [assetMap['/main.js']]
});
return new Response(prelude, {
headers: { 'content-type': 'text/html' },
});
}

サーバーが `` をレンダリングするようになったため、ハイドレーションエラーを回避するには、クライアント側でも `assetMap` を使用してレンダリングする必要があります。次のように、`assetMap` をシリアライズしてクライアントに渡すことができます。

// You'd need to get this JSON from your build tooling.
const assetMap = {
'styles.css': '/styles.123456.css',
'main.js': '/main.123456.js'
};

async function handler(request) {
const {prelude} = await prerender(<App assetMap={assetMap} />, {
// Careful: It's safe to stringify() this because this data isn't user-generated.
bootstrapScriptContent: `window.assetMap = ${JSON.stringify(assetMap)};`,
bootstrapScripts: [assetMap['/main.js']],
});
return new Response(prelude, {
headers: { 'content-type': 'text/html' },
});
}

上記の例では、`bootstrapScriptContent` オプションは、クライアント側でグローバル変数 `window.assetMap` を設定する追加のインライン `