SPA(Single Page Application)と利用されるレンダリング技術まとめ

目次

はじめに

この記事では現代のフロントエンド開発のトレンドである(?)SPA(Single Page Application)とその構築に利用されるレンダリング技術に関して、色々調べて&実際に僕より遥かにベテランの方に教えてもらって情報をたくさんインプットしたのでまとめます。

なるべく前提条件等を明示的に記載した上で執筆しようと思いますが、解釈の仕方どうこうの問題ではなく明らかに間違っている内容があればコメント頂けますと幸いです。
(技術マウントは要りませぬ…)

まず、なぜこの記事を書こうと思ったのかというとこれまでタイトルの技術領域に関して以下のような解釈をしていました。

SPA(シングルページアプリケーション)という大きな括りの中でCSR/SSR/SSGというレンダリング技術が存在する

Twitterでフォロワーさんがピックアップしていたこちらの記事を読んで「あれ、僕の認識と結構違うぞ?」となって色々調べました。

調べてスライドにまとめて、2021/11/27(土)に開催した僕が運営する「つながる勉強会」でこの本記事と同じテーマについて登壇しました。

上の記事にも記載していますが勉強会で登壇した内容にいくつか誤りがありましたのでスライドを修正しています。

こちらが修正したスライドです↓

SPA/CSR/SSR/SSGまとめ

結論、僕が当初持っていた解釈であるSPA(シングルページアプリケーション)という大きな括りの中でCSR/SSR/SSGというレンダリング技術が存在する」というのは大体は間違っておらず、足りないところがいくつかあるという感じでした。

上記スライドでは載せきれない情報があるのと、せっかく色々教えてもらったのでちゃんと残しておこうと思います。

前提

この記事ではフロントエンド開発、つまりJavaScriptを使った開発の話です。

なお、この記事で使用している図は先ほど掲載したスライドの一部です。

SPA(Single Page Application)について

SPAとは先述していますがSingle Page Application(シングルページアプリケーション)の略。

シングルページアプリケーションとは、Webアプリケーションの構成法の一つで、Webブラウザ側でページの移動を行わず、最初に読み込んだWebページ上のスクリプトがサーバとの通信や画面遷移を行う方式。

https://e-words.jp/w/%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%83%9A%E3%83%BC%E3%82%B8%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.html

上にも書いていますが、SPAはアプリケーションを構成するページが1枚しかなく、その1枚のページ上でJavaScriptを使ってページの中身を切り替えることによりページ遷移のような動きを表現します。

文字通り、1つのページで構築されたアプリケーションです。

では、SPAに使用されるレンダリング技術についてまとめます。

CSR(Client Side Rendering)について

CSRとは

Client Side Rendering(クライアントサイドレンダリング)の略。

文字通り、クライアントサイド(ブラウザ)で行うレンダリングのことです。

JS+ReactやVue.jsで開発したアプリケーションは基本的にCSRを行います。(SSRをするためのライブラリは使っていない前提なので「基本」と書いています)

CSRの仕組み

CSRの仕組みを図で表します。

CSRの仕組み

CSRを使ったSPAの場合は、初回アクセスでアプリケーションの構築に必要なリソースを全てクライアントサイドで受け取ります。(リソースに関しては上図では簡易的に表すためHTML/CSS/JSコードを書いていますが、その他にも画像、PDF等がある可能性もあります)

受け取ったリソースを用いてクライアントサイド(ブラウザ)でページをレンダリングを行います。

レンダリングしてくれるのは読み込んだ JavaScriptコードです。

ページをレンダリングする上でDBに格納されたデータの取得をバックエンドのAPIに依頼する場合はクライアントからバックエンドのWeb サーバーにリクエストを送ることでJSONデータを取得します。

バックエンドのAPIにアクセスする目的がDBに格納されたデータの取得、バックエンドから返却されたデータがJSONデータである、ことはそれぞれ一例でCSRが全てそうであるべきではありません。

上記のリクエストの流れは例えばReactであればuseEffectAxiosを使うことで実現できます。

仕組みのまとめとして例えばですが、「CSRだけを使ってDBに登録した投稿データを一覧表示する画面を表示する」ケースは以下の順序です。

  1. クライアントからWebサーバーにGETリクエストを送る
  2. フロントエンド用Webサーバーはアプリケーションを構築する全てのリソースをクライアントに返却する
  3. クライアントでは受けとったリソースを使って一覧画面をレンダリング・描画する(この時点ではDBに登録されているデータは描画されていない)
  4. DBに登録されている投稿データを取得するためにクライアントからバックエンド用WebサーバーにGETリクエストを送る
  5. バックエンド用Webサーバー上で動くAPIで取得したJSONデータをクライアント返却する
  6. クライアントで受けとったJSONデータとJavaScriptを使って投稿データ一覧表示画面をレンダリング・描画する(完成)

CSRのメリット・デメリット

メリット

  • 画面遷移の度にWebサーバーにHTMLを要求する必要がなく、クライアント(ブラウザ)で行うため画面遷移が高速(ブラウザのリロードマークもくるくるならない)
  • SSR、SSG(SG)と比較して実装が楽

デメリット

  • Webサーバーへの初回リクエストでアプリケーションに必要なリソースを全てを受け取る必要あるため、レンダリングするので初期表示が遅い
  • ページ単位にOGPが設定することができない(1つのページのアプリケーションなのでそりゃそうか)
  • SEO的に微妙?(※元々SPAは後述するSSR、SSGよりSEO的に不利だったので最近はそこまでは大差ないようです。この辺は結局どうなのかがよくわかっていません)

SSR(Server Side Rendering)について

JavaScriptでCSRだけで実装したSPAを開発する時のデメリットをカバーできるのがSSRです。

登場の順序的に「CSR→SSR」みたいな流れで紹介する記事がありますが、登場の順序としてはSSRはとても前から存在する技術です。

例えばLaravelでアプリケーションを開発するとWebサーバーでレンダリングしたHTMLをクライアントに返すのでこれも立派なSSRだと思います。

という前提を置きつつ、JavaScriptでのお話をしていきます。

SSRとは

Server Side Rendering(サーバーサイドレンダリング)の略。

これもCSR同様文字通りですが、サーバーサイドで行うレンダリングのことです。これはアクセスのたびに行われます。

SSRはNext.js、Nuxt.js等のフレームワークを使うことで比較的手軽に実装することができます。

(Next.jsは初めはSSR用のReactフレームワークとして登場したそうな)

僕自身やったことはないですが、JS+React、VueアプリケーションでもSSR用ライブラリを追加すればSSRを実装することができるはずです。(まあそれするなら初めからNext.jsとかNuxt.jsで作ろうよと思いますけどね)

SSRの仕組み

SSRの仕組みを図で表します。

SSRの仕組み

SSRはサーバーサイドでレンダリングですから、クライアントからのリクエストを受けとったWebサーバー(フロントエンド用)でページをレンダリングします。

レンダリングする時にDBに登録されているデータを取得する必要がある場合にはDBにアクセスできるアプリケーションが存在するWebサーバーにフロントエンド用のWebサーバーからリクエストを送り、データを受けとります。

上図ではデータのやり取りはJSONとしていますが、必ずJSONである必要はありません。

これもCSRと同様のケースですが「SSRだけを使ってDBに登録した投稿データを一覧表示する画面を表示する」時の手順は以下のようになります。

  1. クライアントからフロントエンド用WebサーバーにGETリクエストを送る
  2. フロントエンド用WebサーバーはDBに登録されている投稿データを取得するためにバックエンド用WebサーバーにGETリクエストを送る
  3. バックエンド用Webサーバーはフロントエンド用Webサーバーに投稿データを返却する
  4. フロントエンド用Webサーバーで受けとった投稿データとHTML/CSS/JS等のリソースを使用してページをレンダリングする(Node.js環境)
  5. DBに登録されている投稿データを取得するためにクライアントからバックエンド用WebサーバーにGETリクエストを送る
  6. フロントエンド用Webサーバーはレンダリング結果をクライアントに返却する
  7. クライアントで受けとったHTMLを描画する

WebサーバーはデフォルトだとJavaScriptを実行できないので、JavaScriptを使用してSSRするためにはサーバーサイドでJavaScriptを実行するためにNode.jsが必要です。

よく言われますがNode.jsはプログラミング言語ではなくJavaScriptの実行環境です。JavaScriptを実行できる環境はブラウザとNode.jsです。(多くのブラウザやNode.jsの内部にはv8エンジンというJavaScriptを評価して実行するエンジンが組み込まれているようです)

SSRはページレンダリング技術であり、SSRされたページのUIを動的に変更するためにはクライアントでレンダリングを行います。

CSRだけで実装したSPAと同規模のアプリケーションにSSRを使用する場合、複数ページをSSRするSPAではなくMPA(マルチページアプリケーション)となります。

では「SSRだと必ずMPAになるのか?」と言えばそれはYESとは言い切れないかと思います。

例えば以下の場合(僕自身が実際に構築できる自信とか置いておきます)はSSRを使用しているけど、SPAです。

  • クライアントでSSRしたHTMLを受けとってCSRする
  • 1つのページのみSSRして以降の画面遷移やサーバーとの通信はクライアントで行う

上記はCSR+SSRで構築されたSPAとなります。

なので僕の今の認識では

SSRはサーバーサイドで行うレンダリングであり、SPAにもMPAにも使用される

です。

SSRのメリット・デメリット

メリット

  • 初めのリクエストで全てのリソースを読み込む必要がないため、CSRより画面表示が早い
  • 複数ページのアプリケーションを構築できるので、ページ単位でOGPの設定・SEO対策が可

デメリット

  • Webサーバーでレンダリングする環境が必要であり、JavaScriptを使用する場合はNode.jsを準備する必要がある
  • 上記の理由によりSPAと比べると実装が複雑で難易度高

SSG(Static Site Generator)について

SSRで発生してしまうサーバー絡みのアレコレをなくしたのがSSG。

SSGとは

SSGはStatic Site Generatorの略です。(日本語では「静的サイトジェネレーター」と呼ぶ)

Next.jsドキュメント(下リンク)ではSSGという言葉は一切出ておらず、SG(Static Generation)という呼び方をされているのでSGでも通用すると思います。
ただ、この記事では現状広く普及しているSSGという言葉を使います。

仕組みはこれから書きますが、SSGの思想としては

アプリケーションをデプロイする段階とかでデータ取得もしておいて、ビルドして取得データも込み込みのページを作成してWebサーバーに配置しておけば良いじゃん

という感じです。

デプロイする段階とか」と書いたのはビルドがデプロイ時に必ず行われるわけではなく、それは設定次第だからです。

Next.jsではNext.jsで開発するアプリケーションはなるべくSSG(SG)を使うことを推奨しており、デフォルト設定のまま例えばVercel(Next.jsの開発元が提供するホスティングサービス)にデプロイしたタイミングでビルドを行い、SSGを行ってくれます。

Next.jsでの話ですが、SSG用のメソッドであるgetStaticPropsを使えば事前にバックエンドのAPI等からデータを取得した上でそのページをSSGします。(「SSGする」という言い方はSSGの意味的には合っていないかもですが…)
なお、SSR用のメソッドであるgetServerSidePropsを使用すればそのページはSSRで生成します。
どちらも指定しない場合はSSGです。

SSGはNext.js、Nuxt.jsを使うことで実装することができます。

キャッチアップができないので確かですが、最近登場したフロントエンド開発での新しいフレームワークであるRemixはSSGできなかったような…

SSGの仕組み

SSGの仕組みを図示します。

SSGの仕組み

他のレンダリング技術と同じく「SSGを使ってDBに登録した投稿データを一覧表示する画面を表示する」時の手順は以下のようになります。

  1. アプリケーション側で事前にビルドした時にバックエンド用Webサーバーから投稿データを取得した上でページをレンダリングしておき、フロントエンド用Webサーバーに配置しておく。
  2. クライアントからフロントエンド用WebサーバーにGETリクエストを送る
  3. フロントエンド用Webサーバーはレンダリング済みのHTMLをクライアントに返却する
  4. クライアントで受けとったHTMLを描画する

SSGはフロントエンド用Webサーバーでレンダリングしないので、Node.js(サーバーサイドでのJS実行環境)が不要です。

SSGで生成された静的なページをクライアントで表示させた後にUIを動的に変更する際にはCSRを行います。

SSGを複数ページに適用したアプリケーションはMPAになりますが、SSR同様「SSGだと必ずMPAになるのか?」の答えはNOだと思います。

例えば以下の場合はSSGを使用したSPAです。(実装したことない)

  • SSGで生成されたHTMLをクライアントで受けとり、さらにそこからCSRして描画する
  • 1つのページのみSSGで生成し、以降の画面遷移やサーバーとの通信はクライアントで行う

上記はCSR+SSGで構築されたSPAとなります。

なので僕の今の認識では

SSGはビルド時に事前に静的なページをレンダリングする技術であり、SPAにもMPAにも使用される

です。

フロントエンド開発でのレンダリング技術をまとめている技術記事の多くは(この記事もそうですが)CSR→SSR→SSGの順で説明しており、そうするとSSGが最も優れているかと思ってしまいそうですが必ずしもそうではないと考えます。

後述しますが、例えばDBに保存しているデータを一覧表示するページをSSGで生成した場合、DBのデータの変更(追加・更新・削除)をUIに反映するためにはその都度ビルドが必要となります。

なのでTwitterのようにユーザーが頻繁にコンテンツを増やしたり消したりして画面の表示が頻繁に変わるようなアプリケーションには適さず、ブログのような管理者がコンテンツを増減したい時に増減するようなアプリケーションに適してるといったようにアプリケーションの性質から考えて適するレンダリング方法が異なります。

余談ですが、最近はNext.js or Nuxt.js + MicroCMS(ヘッドレスCMS)の構成(JAMStack)でのブログで技術記事を投稿しているエンジニアが増えています。

SSGのメリット・デメリット

メリット

  • ページのレンダリングを事前に済ませておくのでページの表示がSPA、SSRより高速
  • サーバーサイドでのレンダリング実行環境(Node.js)が不要
  • ページ単位でOGPの設定が可能
  • SEO対策が可能

デメリット

  • ページ数が多いアプリケーションではビルド時間が長くなる
  • 画面に表示するコンテンツが頻繁に変更される場合、その変更の反映にはビルドが必要になる(Twitterのように多くのユーザーがコンテンツを登録したり削除したりするものは適さない)

SPA=CSRなのか?

この記事の最後に紹介しているSPA、CSR、SSR、SSG周りの記事では「SPA=CSR」と書かれているものが結構ありますが、これは正確には間違いです。(同義語ではないという意味)

感じの悪い書き方をしていますが、概要を掴むのにとても助かりました。執筆者の皆さんには感謝しています。

まず、SPAは「アプリケーション」であり、CSRは「技術・仕組み」なので言葉のレベル的にイコールにはなりません。

SPAを構築するためにCSRは必須です。

必須ですが、CSRに加えてSSR、SSGを使ってSPAを構築することも可能なのでそういう意味もふまえてイコールではないと考えます。

ということで、よく技術記事は

  • SPA(=CSR)
  • SSR
  • SSG

が同じレベルでまとめられていますが、これも正しくはないと考えます。(部分的に合っているところもあるので「間違っている」とは言えない)

色々な記事を読み、周りのエンジニアに教えてもらい、実際にこの記事を書いた上でSPAとCSR/SSR/SSGの関係というか立ち位置なのかについて僕なりに出した総括的な考えをまとめようと思います。

まとめ

まずはそれぞれの方式の特徴を表にまとめます。

レンダリング技術レンダリングNode.jsが必要SPA構築に必須MPA構築が可能
CSRクライアント
SSRサーバーサイド
SSGビルド時
レンダリング技術の特徴

その他の特徴なり所感はこちら。

  • SPA(=CSR)/SSR/SSGという仲間分けではなく、SPAを構築するレンダリング技術としてCSR/SSR/SSGは存在する
  • SPAを構築するのにCSRは必須、SSR、SSGは必須ではない
  • JavaSvriptでマルチページアプリケーション(MPA)を構築する場合はSSRもしくはSSGを使うことで可能である
  • SSRもSSGもそのページの初期レンダリングの方法であり、それ以降の差分のレンダリングは全てCSR
  • SPA、SSR、SSGそれぞれにメリット・デメリットがあるので一概にどれが優れているわけではなく、開発したいアプリケーションの特徴によって上手に選定するのが大事
  • と書きつつ、現状はなるべくにSSGを使うのが推奨されている流れ(と思います)

最後に

こうやってガッツリ記事を書いてみるといかに自分がフワッとした理解してしていなかったのかいかに勘違いしていたのかがわかりました(笑)

ただ、記事を書いてかなり理解度が深まったので時間をかけて記事を執筆した甲斐があったなと思います。(これまでのブログ記事の中で1番時間を要したかもしれませんw)

CSR、SSR、SSGの仕組みとかメリデメは個人的にはかなり理解が深まったのですが、HTMLレンダリングの細かいところとかやビルドとかまだ理解が浅いところがあるのでまた調べてブログにまとめたいです。

結論:フロントエンドは難しいっっ!!!!!!

参考記事

大変勉強になる記事ばかりでした。感謝です。

Udemyのオススメ講座

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!

この記事を書いた人

大学院(機械工学)→重工業→Webエンジニア

PHP/Laravel/TypeScript/React/Next.js/Vue.js/Nuxt.js

神戸で「つながる勉強会」を運営↓
https://tsunagaru-kobe.connpass.com/

目次
閉じる