docs-rsc-sandpack について
SandpackでRSCの例を作るReactドキュメント執筆者向けのパターンガイドです。サーバーとクライアントのファイル指示子、Server Functions、必要な構成を説明します。
主な機能
- 01サーバーとクライアントの指示子の説明
- 02非同期コンポーネントとSuspenseの解説
- 03Server Functionsのパターン紹介
- 04エントリーポイントと依存関係の制約
活用シーン
- 01ドキュメントにRSCの対話型サンプルを追加
- 02Sandpack RSCのファイル構成の問題を調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ reactjs/ react.dev --skill docs-rsc-sandpackインストール後、Claude Code で/docs-rsc-sandpackを入力して読み込まれたか確認します。
詳細
RSC Sandpack のパターン
一般的な Sandpack の規約(コードスタイル、命名、ファイル名、行のハイライト、隠しファイル、CSS ガイドライン)については、/docs-sandpack を参照してください。このスキルでは、RSC 固有のパターンのみを扱います。
クイックスタートテンプレート
最小限の単一ファイル <SandpackRSC> の例:
<SandpackRSC>
` ` `js src/App.js
export default function App() {
return <h1>Hello from a Server Component!</h1>;
}
` ` `
</SandpackRSC>
<Sandpack> との違い
| 機能 | <Sandpack> | <SandpackRSC> |
|---|---|---|
| 実行モデル | すべてのコードが iframe で実行されます | サーバーコードは Web Worker で、クライアントコードは iframe で実行されます |
'use client' ディレクティブ | 無視されます(すべてクライアント側です) | クライアントコンポーネントを指定するために必要です |
'use server' ディレクティブ | サポートされていません | クライアントから呼び出せるサーバー関数を指定します |
async コンポーネント | サポートされていません | サポートされています(サーバーコンポーネントは非同期にできます) |
| 外部依存関係 | package.json 経由でサポートされています | サポートされていません(React + react-dom のみ) |
| エントリーポイント | export default を含む App.js | export default を含む src/App.js |
| コンポーネントタグ | <Sandpack> | <SandpackRSC> |
ファイルディレクティブ
ファイルは、ファイルの先頭にあるディレクティブによって分類されます。
| ディレクティブ | 実行場所 | ルール |
|---|---|---|
| (なし) | Web Worker(サーバー) | デフォルトです。async にできます。他のサーバーファイルをインポートできます。フック、イベントハンドラー、ブラウザー API は使用できません。 |
'use client' | Sandpack iframe(ブラウザー) | 最初の文でなければなりません。フック、イベントハンドラー、ブラウザー API を使用できます。async にはできません。サーバーファイルをインポートできません。 |
'use server' | Web Worker(サーバー) | サーバー関数を指定します。モジュールレベル(すべてのエクスポートがアクション)または関数レベルで使用できます。props またはフォームの action 経由でクライアントから呼び出せます。 |
よくあるパターン
1. サーバーコンポーネント + クライアントコンポーネント
<SandpackRSC>
` ` `js src/App.js
import Counter from './Counter';
export default function App() {
return (
<div>
<h1>Server-rendered heading</h1>
<Counter />
</div>
);
}
` ` `
` ` `js src/Counter.js
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
` ` `
</SandpackRSC>
2. Suspense を使った非同期サーバーコンポーネント
<SandpackRSC>
` ` `js src/App.js
import { Suspense } from 'react';
import Albums from './Albums';
export default function App() {
return (
<Suspense fallback={<p>Loading...</p>}>
<Albums />
</Suspense>
);
}
` ` `
` ` `js src/Albums.js
async function fetchAlbums() {
await new Promise(resolve => setTimeout(resolve, 1000));
return ['Abbey Road', 'Let It Be', 'Revolver'];
}
export default async function Albums() {
const albums = await fetchAlbums();
return (
<ul>
{albums.map(album => (
<li key={album}>{album}</li>
))}
</ul>
);
}
` ` `
</SandpackRSC>
3. サーバー関数(アクション)
<SandpackRSC>
` ` `js src/App.js
import { addLike, getLikeCount } from './actions';
import LikeButton from './LikeButton';
export default async function App() {
const count = await getLikeCount();
return (
<div>
<p>Likes: {count}</p>
<LikeButton addLike={addLike} />
</div>
);
}
` ` `
` ` `js src/actions.js
'use server';
let count = 0;
export async function addLike() {
count++;
}
export async function getLikeCount() {
return count;
}
` ` `
` ` `js src/LikeButton.js
'use client';
export default function LikeButton({ addLike }) {
return (
<form action={addLike}>
<button type="submit">Like</button>
</form>
);
}
` ` `
</SandpackRSC>
ファイル構成の要件
エントリーポイント
- メインのエントリーポイントとして
src/App.jsが必要です export default(関数コンポーネント)を含める必要があります- 大文字と小文字を区別しないフォールバックとして、
src/app.jsも使用できます
自動注入されるインフラストラクチャファイル
これらのファイルは sandpack-rsc-setup.ts によって自動的に注入されるため、MDX に含めないでください。
| ファイル | 目的 |
|---|---|
/src/index.js | RSC パイプラインを起動します |
/src/rsc-client.js | クライアントブリッジ — Worker を作成し、Flight ストリームを消費します |
/src/rsc-server.js | 事前バンドルされた Worker ランタイムを ES モジュールとしてラップします |
/node_modules/__webpack_shim__/index.js | 最小限の webpack 互換レイヤー |
/node_modules/__rsdw_client__/index.js | ローカル依存関係としての react-server-dom-webpack/client |
外部依存関係なし
<SandpackRSC> は外部 npm パッケージをサポートしていません。利用できるのは react と react-dom のみです。RSC の例には package.json を含めないでください。
アーキテクチャのリファレンス
3 層アーキテクチャ
react.dev page (Next.js)
┌─────────────────────────────────────────┐
│ <SandpackRSC> │
│ ┌─────────┐ ┌──────────────────────┐ │
│ │ Editor │ │ Preview (iframe) │ │
│ │ App.js │ │ Client React app │ │
│ │ (edit) │ │ consumes Flight │ │
│ │ │ │ stream from Worker │ │
│ └─────────┘ └──────────┬───────────┘ │
└───────────────────────────┼─────────────┘
│ postMessage
┌───────────────────────────▼─────────────┐
│ Web Worker (Blob URL) │
│ - React server build (pre-bundled) │
│ - react-server-dom-webpack/server │
│ - webpack shim │
│ - User server code (Sucrase → CJS) │
└─────────────────────────────────────────┘
主要なソースファイル
| ファイル | 目的 |
|---|---|
src/components/MDX/Sandpack/sandpack-rsc/RscFileBridge.tsx | Sandpack を監視し、未加工のファイルを iframe に送信します |
src/components/MDX/Sandpack/SandpackRSCRoot.tsx | SandpackProvider のセットアップ、カスタムバンドラー URL、UI レイアウト |
src/components/MDX/Sandpack/templateRSC.ts | RSC テンプレートファイル |
.../sandbox-code/src/__react_refresh_init__.js | React Refresh シム |
.../sandbox-code/src/rsc-server.js | Worker ランタイム:モジュールシステム、Sucrase コンパイル、renderToReadableStream() |
.../sandbox-code/src/rsc-client.source.js | クライアントブリッジ:Worker の作成、ファイルの分類、Flight ストリームの消費 |
.../sandbox-code/src/webpack-shim.js | 最小限の __webpack_require__ / __webpack_module_cache__ シム |
.../sandbox-code/src/worker-bundle.dist.js | 事前バンドルされた IIFE(生成物):React サーバー + RSDW/server + Sucrase |
scripts/buildRscWorker.mjs | esbuild スクリプト:rsc-server.js を worker-bundle.dist.js にバンドルします |
ビルドシステム
Worker バンドルの再ビルド
rsc-server.js または webpack-shim.js を変更した後:
node scripts/buildRscWorker.mjs
これにより、次の設定で esbuild が実行されます:
format: 'iife'、platform: 'browser'conditions: ['react-server', 'browser'](React サーバーのエクスポート条件を有効化します)minify: true- 出力の先頭に
webpack-shim.jsを追加します
Raw-Loader の設定
templateRSC.js では、ファイルは !raw-loader を使って未加工の文字列として読み込まれます。
これらの文字列は、Sandpack にローカルファイルとして渡すために必要です(Sandpack によるバンドルを回避します)。
開発コマンド
node scripts/buildRscWorker.mjs # Rebuild worker bundle after source changes
yarn dev # Start dev server to test examples
コメント
Markdown 対応