Open8

CSR, SSR とかの整理

おーみーおーみー

用語整理。

レンダーという言葉について

CSR、SSR などの単語における「レンダー」(render) という単語は「React/Vue の要素を HTML 要素に変換する」程度の意味合いで使われている。ブラウザが HTML/CSS から Web ページを画面に表示することもレンダーと呼ばれるが、異なる。

本質はどこ?

ものによるが、本質がdata fetchingである可能性もありそう。Next.jsのドキュメントではSSR/SSGの使い分けのようなものではなくdata fetchingと題されているので。

おーみーおーみー

CSR

client side rendering。ブラウザ上で ReactDOM.render() を実行してReact要素をHTML [1] に反映させる。

初回ロードされるHTMLにはコンテンツが含まれていないので非常に薄く、<div id="react-root"></div> のようなマウントターゲットとなる要素が置かれているぐらい。

  • HTMLを読み込んでからJSを取得して実行することでコンテンツが読み込まれるため初回ロードに影響がある
  • HTML/CSS/JSだけで完結するのでデプロイ先にはGitHub Pagesなども選択できる
  • JSを実行しないとコンテンツが取れないので検索エンジン最適化に弱いという説があるが、最近のクローラはJSを解釈できるという説もある
  • アカウントによって表示が異なるなどの場合分けがあり、Webアプリケーション向き
脚注
  1. なんて呼べばいいのかわからない。DOMツリー? ↩︎

おーみーおーみー

SPA

single page application。react-routerやvue-routerを使ってブラウザ上でのページ遷移を疑似的に再現しているアプリケーション。リンクをクリックしたときにはページの一部または全部を差し替えブラウザのURLを変更しHistory APIを使って履歴を追加する。

single pageというのは、ブラウザはページ遷移しているようにみえて実際には1ページで完結してるからだと思う。CSRとほぼ同義な気がするのはCSRがWebアプリケーション向けの特性を持っているから。SPAの技術はSSRやSSGの際にも使われることがある。

おーみーおーみー

SSR

server-side rendering。リクエストが来たときにサーバー上で ReactDOM.renderToString を実行してReact要素をHTML文字列に起こして返し、クライアント上で ReactDOM.hydrate を実行して React の管理下にする。

初回ロードされるHTMLにはコンテンツが含まれる。

  • コードを実行できるサーバーが必要になる
    • サーバーはNext.js/Nuxt.jsの場合Node.jsだが、ReactDOMが動けばいいのでCloudflare Workersなどでもできる。Remixのことを言っている。
  • Next.jsでは getServerSideProps を使うとリクエストが来た時に実行できる
  • SSGと比較して、リクエスト時にコンテンツを生成するので
    • 理論上遅くなる
    • 外部APIへのリクエストなどを毎回行えるので
      • コンテンツが頻繁に変更される場合即座に反映できる
      • APIを頻繁に呼ぶので時間的・金銭的コストがかさむ

GoやPHPやRubyで立てたサーバ上でHTMLテンプレートを使ってHTMLを動的に返すのに似ているが、ReactDOM.hydrate される点が異なる。

GatsbyなどのSSGするツールにおいて ReactDOM.renderToString することを「SSR」と呼んでいることがある (gatsby-ssr.js など)。

おーみーおーみー

SSG

static site generator。Reactよりも前からある言葉っぽい。原義はGoやPHPなどでHTMLテンプレートを使ってprogrammaticalにWebサイトを生成するもの。HugoとかJekyllとか。

SSRなどと対比される場合のSSGとは、適当なマシン上で ReactDOM.renderToString を実行してReact要素をHTML文字列に起こしたものをデプロイし、リクエストがあったときはそれを単純に送信し、ブラウザ上で ReactDOM.hydrate するもの。Gatsbyはもともとこの意味でのSSGに特化したフレームワーク。

SSRとSSGでやっていることは同じで、タイミングが異なるだけ。

  • SSRと比較して、デプロイ前にコンテンツを生成するので
    • リクエストに対する応答が早い
    • WebサーバーはHTML/CSS/JSを返すもので十分
      • GitHub Pagesなどにも載せられる
    • コンテンツ変更のたびにビルドしなおしが必要なので、頻度が低いと良い
  • Next.jsでは getStaticProps を使うと next build 時に実行される
    • Next.jsではサイトではなくページ単位で使い分けるのでstatic generationと呼ぶことがある
  • デプロイ前にすべてのページをレンダーするのでページが増えるほどデプロイに時間がかかる
おーみーおーみー

ここからまったく自信ないゾーン。

ISR

incremental static regeneration。Next.jsの機能。中核コンセプトとしては「getStaticPropsでのSSGをリクエスト時に行える」というところか。

まず、eコマースサイトの各商品のうち人気の1000件だけを静的生成して残りの9000件はリクエスト時 (on-demand) に生成することでデプロイ時間を短縮、という使い分けテクニックが可能。

さらに、revalidate に秒数指定ができる。この秒数は「生成したページがどのくらいの間有効か」を示している。ページ生成後n秒以内に来たリクエストに対しては生成済みのファイルを渡し、n秒以降に来たリクエストに対しては生成済みのファイルを渡しつつ裏側で再生成を行いキャッシュを更新する。キャッシュ更新後のリクエストにはその新しいページが返され、n秒経過後のリクエストに対してはまた再生成が走り…という流れ。

https://vercel.com/docs/concepts/next.js/incremental-static-regeneration

  • SSGと比較して、単一ページごとに再生成が行えるため情報が頻繁に更新されるコンテンツでもビルド時間がかからない
  • SSRと比較して、指定秒数内のリクエストではいちいち生成を行わないのでコストがかからない
  • 一方で、指定秒数内のリクエストではページが使いまわされてしまうのでデータの更新に即座に反応できない
  • さらに、Vercelでないと使えない
    • 秒数指定のあたりっぽそう

実際に運用してみないとわからないところがあるが、検証するのがめんどくさそう。