Next.jsでReact18の機能を試してみる
- Streaming SSR
- React Server Components
- Switchable Runtime
を試してみる
Next.jsでReact Server Componentsを使う作業ログ
next@canary react@latest react-dom@latest
を入れて、next.config.jsを指定すれば使える
module.exports = {
experimental: {
runtime: 'nodejs',
serverComponents: true,
},
}
サンプルリポジトリだとビルドを実行すると
Page Size First Load JS
┌ ○ / 1.05 kB 84.5 kB
├ ○ /404 194 B 79.5 kB
├ ○ /csr 632 B 90.3 kB
├ ℇ /item 2.24 kB 114 kB
├ ℇ /rsc 2.72 kB 111 kB
├ ℇ /slow 2.66 kB 111 kB
└ ℇ /ssr 2.87 kB 89 kB
+ First Load JS shared by all 79.4 kB
├ chunks/framework-a87821de553db91d.js 45 kB
├ chunks/main-6f7a5663a306f0a0.js 32.7 kB
├ chunks/pages/_app-9538641435026bd3.js 824 B
└ chunks/webpack-9b312e20a4e32339.js 836 B
ℇ (Streaming) server-side renders with streaming (uses React 18 SSR streaming or Server Components)
○ (Static) automatically rendered as static HTML (uses no initial props)
ℇ (Streaming) server-side renders with streaming (uses React 18 SSR streaming or Server Components)
になるけど、runtimeに 'nodejs'で試すと、この形式にはならない
nodejsだとReact Server Componetsを使った際に画面が描画されなくなるので
とりあえずサンプルリポジトリと一緒のruntime: 'edge',
を指定する
ドキュメントに記載されている"next": "canary",
を使う場合は
edge
の部分をexperimental-edge
に指定することでReact Server Componentを使用できる
module.exports = {
experimental: {
runtime: 'experimental-edge',
serverComponents: true
}
};
export const config = {
runtime: 'experimental-edge'
};
yarn dev
は動かないけど、yarn build
してからyarn start
すると動く
server-side renders with streaming (uses React 18 SSR streaming or Server Components)
ってあるけどSSR streamingする場合とServer Componentsになる場合の違いはなんじゃろ
pageにgetServerSideProps
を定義してそこでSuspense読んでもStreamingにはならない
ssrのpageに
export const config = {
runtime: 'experimental-edge'
};
するとstreamingになる
基本的にSSRでもCSRでもserverコンポーネント使ってるページでも上のconfigをexportすればstreamingとして扱われる
- csrのページでconfigをexportするとyarn devでもSuspenseの挙動を確認できる
- ssrはドキュメントに記載されてる通り、yarn devだとエラー
- server componentsはそもそもyarn devでは動かない
SSR Streamingを有効にするにはWeb streamと互換性のあるランタイムを使う必要がある
HTTP Streamingの話
初回のリクエストをサーバー側が受け取ると、そこからはサーバー側からレスポンスがプッシュされる
Streaming SSRについて
- ネットワークを介して複数のチャンクをロードする
- React18で実装されたrenderToReadableStream
- renderToReadableStream: Deno や Cloudflare Workers のようなモダンなエッジランタイム環境用
- これはサーバー側でSuspenceをストリーミングする機能を持ってる
Streaming SSR
- Suspenseで囲まれたコンポーネント以外は先にSSRしてHTMLを返す
- Suspenseで囲まれたコンポーネントのレンダリングはSuspense内でthrowされたPromiseが解決されるとサーバー側からプッシュされて、再レンダリングされる
- Promiseが解決されるとHTMLが追加される
- これにより初回のHTMLの描画は向上され、Suspense内のコンポーネントは後続のサーバー側からのプッシュで描画される
Server Componentsはまだ実験段階だが18のマイナーリリースで初期バージョンをリリースする予定
当面はNext.js、Hydrogen、Remixなどのフレームワークを使用して試してみてる
Layouts RFCをざっくり読む
Next.jsの新しいLayoutsはReact18の簡単に採用できるように設計されている
Next.jsでは新しいlayoutの機能を実装することで、今よりも、よりパフォーマンスを向上させたり、リッチなアプリケーションを簡単に作れるようになりたい
新しい機能のルーティングはpagesじゃなくてappでできるようになる
後方互換性があるように今までの状態で使いたい場合は引き続きpagesを使うと良い
appディレクトリ内でのルーティングはファイルではなくフォルダーが基本になる
いままで、拡張子の設計を変える以外にpages配下にルーティング用のファイル以外を置く方法がなかったが、appディレクトリ内はルーティングが基本、ディレクトリになるのでテストやStorybookなど別のファイルも置けるように
appディレクトリ内でlayout.jsを定義すると画面遷移で再レンダリングされない(状態管理を保ったまま)のコンポーネントを定義できる
このlayout.jsはappディレクトリ内の構造のようにネストすることができる
いままでpages配下に配置していたpage用のファイルはappディレクトリ内ではpage.jsで定義する
appディレクトリでつくる新しいルーティングはReact18の機能を活用して実装されている
appのディレクトリないのファイルはデフォルトではServer Componentsを使ってサーバーサイド側でレンダリングされるようになる
Server ComponentとClient Componentの機能と制約
app内のlayoutとpageコンポーネントはサーバーサイド、クライアントサイド、その両方のどれでも選択できる
いままでNext.jsでは、いつ、どこでレンダリングするかは、Next.jsのデータフェッチの関数を使用することで選択していた
appディレクトリでは、レンダリングの方式はデータフェッチとは切り離され、コンポーネントレベルで選択されるようになる
layoutファイルではgetStaticPropsとgetServerSidePropsが使用できる
親のlayout、子のlayout、pageでのfetchがparalleでできるようになる
https://nextjs.org/blog/layouts-rfc#parallel-fetching
Server Componentsの応答形式