はじめに
どうも、普段はvueとRailsでのSSR環境で仕事をしているのものです。
最近個人開発でNext.jsを使うようになって、新しく追加されたストリーミングというレンダリング方式があることを知ったのでざっとまとめてみました。
SSRの仕組みと限界
まずは、SSRがどんなものか見てから、なぜストリーミングが出てきたのか理解してみたいと思います。
SSRの過程
1. サーバーでのデータフェッチ
まずは、リクエストごとに毎回異なるレスポンスを返すため、データ取得が必要になります
2. HTMLの生成
取得したデータを使用してHTMLを構築
3. クライアントでのコードローディング
サーバーからクライアントへHTML、CSS、JavaScriptを送信
4. Reactによるハイドレーション
ハイドレーションとは、静的なHTMLに対して、EventHandlerなどのJavaScriptコードを追加することです。これでインタラクティブな要素が機能するようになります(useState, useEffectなども含め)
SSRの限界
すべての処理が順次的(シーケンシャル)に行われることがSSRの大きな問題点です。
毎回、更新のある時上記過程が必要になるので非効率ですよね。
例えば、次のようなページ構成を考えてみます。
- おすすめ商品セクション(データ取得が必要)
- フッター(データ取得不要)
このような構成でも、SSRではデータ取得が完了するまでフッターのような静的コンポーネントもレンダリングを待つ必要が出てきます。
つまり、データ取得が不要なレイアウトコンポーネントも、必要なコンポーネントの処理完了を待つ必要があります。そんなに頻繁に変わる必要はないですよね..
ストリーミングによる解決策
Next.jsのストリーミングの特徴
ストリーミングは処理を並列的に行うことでSSRの問題を解決します。
データ取得が不要なコンポーネントは取得を待たずに先行してレンダリングし、チャンク単位(主にコンポーネント単位)でレンダリングを実行します。
Suspenseを使用して、データ取得が必要なコンポーネントと不要なコンポーネントを分けることができます。
実装例
// データ取得が必要なコンポーネントをSuspenseで囲む
<Suspense fallback={<LoadingComponent />}>
<DynamicComponent />
</Suspense>
実際の動作の違いは以下の通りです。
Suspenseなし:データ取得が完了するまで画面全体がブロックされる
Suspenseあり:静的な部分が即座にレンダリングされ、動的な部分はローディング表示の後に表示される
PPR(Partial Pre-Rendering)との比較
PPRはHotwireで使われているもので、
ページ全体をリロードすることなく必要な部分だけを効率的に更新することができる仕組みです。
ストリーミングと似たように見えますが少し違うところがあります。
共通点
- サーバーサイドでの段階的なレンダリングを行う
- 静的コンテンツと動的コンテンツを分離する
主な違い
PPRでは、複数のダイナミックコンポーネントからの個別のHTTPリクエストを単一のリクエストにまとめています
PPR前: コンポーネントごとに複数のネットワークラウンドトリップ(リクエストとレスポンスのこと)が発生
PPR後: 静的レンダリングと動的コンポーネントを1つのHTTPリクエストに統合
このような最適化が入っているのでPPRはストリーミングの進化版とも言えるのですが、まだNext.jsでは実験的な機能です。
まとめ
- SSRには順次的な処理による限界がある
- ストリーミングはSuspenseを使用して並列処理を実現
- データ取得の有無でコンポーネントを分離
- PPRはさらに最適化された実験的な機能
おわりに
Next.js、AIと会話して開発しやすいので個人開発にはいいですね!
地味にストリーミングとかこだわって作っているのですが、もう少しNext.js自体の勉強を頑張った方がいいかもです笑