Top

Appendix

Glossary

言葉の定義

CSR, SSR, SPA, MPA #

夜空を埋め尽くすほどのフレームワークが生まれては消えていくモダンフロントエンドにおいて、CSR, SSR, SPA, MPAといった用語はそれぞれの立ち位置を表現する必須の用語です。しかしながら、これらですら人によって意味がまちまちであり、議論の土台とするのに苦労します。

ここではこのサイトにおける各用語に明確な定義を与え、技術比較の助けにしたいと思います。皆さんの定義とは異なるかも知れませんが、このサイトではこれで通したいと思っています。

私の考え方としては、下表のように各用語に1つだけ意味を与えています。そしてレンダリングと(ブラウザの)メモリ維持という直交する軸に展開しています。

CSR, SSR, MPA, SPAの定義
視点技術名前どこでRenderingされるか?ページ遷移時にメモリは維持されるか?
レンダリングCSRClient-Side Renderingブラウザ不問
SSRServer-Side Renderingサーバ不問
ブラウザ上の
メモリ維持
SPASingle-Page Application不問そもそも遷移がない
または維持される
MPAMulti-Page Application不問維持されない

CSR: Client-Side-Rendering #

定義

  • ブラウザの中でJavaScriptコードが実行されて、その結果としてHTMLを生成(レンダリング)するやり方

メリット

  • サーバに問い合わせることなく、ユーザイベントに対して表示されるHTMLを大きく変更できる

デメリット

  • JavaScriptをロードし、実行するまではHTMLが生成されないので、何も表示されない

SSR: Server-Side-Rendering #

定義

  • サーバでHTMLが生成(レンダリング)され、ブラウザにHTMLが送信されるやり方

メリット

  • JavaScriptをロードする前からHTMLが存在するので、すぐに画面を表示できる

デメリット

  • ユーザイベントに対して大きくHTMLを変更する場合はサーバにHTML生成を依頼するので、サーバへの問い合わせが必要

SPA: Single-Page Application #

  • 全画面を書き換える画面遷移は行わないウェブページ。画面の部分的な置換だけでUI/UXを構成したもの
  • 一見すると画面全体が遷移しているように見えても、実際には<head>タグは保持し、<body>タグの内容だけを更新しているもの(React Router, Next.jsのLinkタグ、およびHotwire Turbo Driveはこれに当たる)

メリット

  • <head>タグで読み込まれるJavaScript, CSSを再読み込みしないので、レスポンスタイムを短縮できる
  • イベントの前後でステートを維持できる – これを活用した最適化等が可能

デメリット

  • ブラウザのネイティブな画面遷移をハイジャックする形になるので、互換性の問題が生じやすい
  • ブラウザのネイティブな機能を使わないので、キーボードショートカットやアクセシビリティの配慮が抜けやすい
  • JavaScriptに依存するので、SEOに不利

MPA: Multi-Page Application #

  • <a><form>でナビゲーションをする際、<head>タグの中身を含めたページ全体をブラウザメモリから消し、まっさらな状態から次のページを描画するもの
  • ブラウザのネイティブな画面遷移

メリット

  • ブラウザネイティブの動作なので、互換性の問題が生じにくい
  • ブラウザネイティブなので、ブラウザ開発者が用意したショートカットやアクセシビリティを活用でき、ウェブページ開発者が配慮することが少ない
  • JavaScriptがなくても動作するので、SEOに強い

デメリット

  • <head>タグで読み込まれるJavaScript, CSSを再読み込みするので、JavaScriptの量が多い場合やブラウザのパワーが貧弱な場合はレスポンスタイムが遅い
  • ナビゲーションイベント前後のステートがクリアされ、維持できない。

判断に迷いやすいケースの解釈 #

上記の定義に従うと、以下のケースの解釈が容易になります。またそれぞれの技術のメリット・デメリットを上述に従って理解できます。

  • SSG (Static-Site Generation)はSSRとして解釈されます。サーバからブラウザに送られるのはHTMLファイルであるため、サーバでレンダリングされたと考えるためです。またNext.jsのISR (Incremental Static Generation)も同様にSSRの1例として考えます
  • Ruby on Rails, PHP, DjangoなどのHTMLテンプレートを使ったウェブページはSSRとして解釈されます。HTMLがサーバでレンダリングされるためです。なおHydrationの有無は上記のSSRの定義には無関係です
  • Next.jsでgetServerSideProps()を使ったページは、状況によってCSRであり、SSRであり、SPAであり、MPAです。
    • 初回ロード時はサーバでHTMLがレンダリングされますのでSSRです
    • Linkタグを使って画面遷移するときは、サーバからJSONが送られてきます。このJSONを使って、JavaScriptがHTMLをレンダリングして、リンク先のページを画面に表示します。よってCSRです
    • Linkタグを使って画面遷移をするときは<head>タグを残して、<body>タグの中だけが(主に)変化します。よってSPAです
    • Next.jsを使用していても、Linkタグではなく、ただのaタグで画面遷移をすることもあります。この場合は<head>タグを含めて、ページ全体がメモリから消去され、次のページはゼロから描画されます。よってMPAです
  • React Server ComponentsはRSC payloadをサーバからブラウザに送ります。これはHTMLにかなり近いもので、HTMLの構造がそのまま記載されています。したがってSSRとして捉えます。Linkタグを使って画面遷移した場合はgetServerSideProps()と同様に判断されます
CSR, SSR, SPA, MPA
CSR, SSR, SPA, MPA description
MPAとSPAのページ遷移
MPA SPA description

レンダリング #

「レンダリング」は一般には画像、映像、音声が出力される処理を指しますが、特にReact SPAの場合はこの意味で使われていません。Reactの場合はデータが画面に表示されるまでの工程が複雑ですので、先にこれを解説します。

  1. 画面に表示されるべきデータがJSON等の形式で取得される
  2. JSONのデータがコンポーネント関数により、ReactNodeのツリーに変換される
  3. ReactNodeのツリーとブラウザのDOM (画面に表示されているもの)が比較され、差分がブラウザDOMに書き込まれる
  4. DOMがブラウザに表示される

一般的な用法により近いのは4.のステージだと思いますが、Reactの世界では主に2.のステージを指しているように思います。そこで本サイトでも「レンダリング」は2.の意味で使用します。広義にはブラウザDOMに反映する直前の状態がレンダリングだと考えており、React Server ComponentsのRSC Payloadの生成もレンダリングと考えています。

Hydration #

ReactでSSRを行い、サーバからブラウザにHTMLを送信した場合、このままではページはインタラクティブになりません。つまりクリックなどに反応しません。インタラクティブにするにはHydrationが必要です。

なぜReact SSRはインタラクティブにならないのか?

ボタンをクリックに応答させるには、ボタンのHTMLにイベントハンドラを接続する必要があります。イベントハンドラとはクリックしたイベントを受け取り、実行されるJavaScriptのことです。しかしサーバがSSRで生成したHTMLにはイベントハンドラがありません。そのため、インタラクティブにはなりません。

Reactではイベントハンドラを接続するために、JavaScriptをダウンロードし、CSRと同じように完全なウェブページをブラウザの中で作り上げます。これは画面には表示せずに、裏でやります。裏で作られたウェブページにはイベントハンドラがありますので、画面に表示されているボタン等にこのイベントハンドラを繋げます。

これを経て、React SSRのページはようやくインタラクティブになります。

ネイティブなMPAやHotwire Turbo DriveではHydrationが不要なのか?

ネイティブなMPAではHydrationは不要です。HydrationをしなくてもHTMLにイベントハンドラがつながり、インタラクティブになります。

JavaScriptはもともとHTMLと分割管理されるように設計されています。そして分割されたものを簡単につなげる仕組みも用意されています。JavaScriptのaddEventListener()関数により、HTMLに簡単にイベントハンドラがつけられます。ReactのHydrationのように裏でウェブページを再構成するような処理は不要です。

HotwireもネイティブなMPAと同様の方法を採用しており、Hydrationなしでイベントハンドラをつなげます。

SEOとSSR #

SEO (Search Engine Optimization:検索エンジン最適化)はGoogle等の検索サイトの上位に表示させる一連の対策を指します。

各検索サイトは"crawler"もしくは"spider"というボットを使って、自動的にインターネットのウェブサイトにアクセスし、その情報を蓄積します。しかし歴史的にはこのボットはJavaScriptを実行できませんでした。CSRを使った場合はHTMLをレンダリングするためにJavaScriptが必要なので、ボットはCSRサイトの情報を収集できなかったというわけです。つまりCSRを使ったサイトは検索サイトの上位に表示されませんでした。

近年ではGoogleのボットはJavaScriptを実行でき、CSRのサイトからも正しく情報収集ができると考えられています。しかしそれでもJavaScriptを必須とするサイトの方が情報収集に時間を要するという話もあり、不利である可能性があります。残念ながらGoogleを筆頭に各検索サイトはアルゴリズムを非公開にしていますので、この辺りは正確な情報が得られません。またJavaScriptを実行するには多くの処理能力を必要とするので、Google以外の検索サイトについては依然としてCSRのサイトを検索できないと言われています。

確実なSEO対策をするのであれば、サーバがHTMLのレスポンスを返すSSRの方が安心でしょう。