【2023年6月版】

私が静的サイトジェネレーター(SSG)を採用した理由

公開日: 2023/06/26
読了時間: 約 16分

本サイトでは Astro の SSG 機能(デフォルト機能)を使ってサイトを構築しています。 Astro + Vercel を使ってサイトをデプロイする顛末は以下の記事に書きました。

が、そもそもなぜ、SSGとAstroを採用したのかという技術選定のプロセスを振り返ってみたいと思います。

静的サイトジェネレーター(SSG)とは?

詳しい記事は以下のサイトをご覧いただくのが良いかと思います。

ざっくり言うと以下のようなものです。

静的サイトジェネレーター(SSG)は、コンテンツ(生データ)とテンプレートを使って全てのページを事前に生成します。つまり、SPAのようにWebサイトをビルドします。 すでにWEBページが生成されているので、リクエストが来てもそのままコンテンツをWebサーバーからクライアントに送信するだけです。これにより、ページの読み込み速度が劇的に向上し、サーバーの負荷も軽減されます。

Wordpress のようなCMSはサーバーの実行中に動的にコンテンツを書き換えられますが、SSGはページを変更して、ビルドして、デプロイする、という手順が必要です。

なのでWordpressのようにどこかのホスティングサービスでボタンを押せば使い始められるCMSとは違い、そこそこの技術者でないとサイトが立ち上げられません。

SSGの概要はこのような感じですが、他のフレームワークとはどう違うのでしょう?

MPA vs SPA

まず初めに、MPAとSPAの比較については本家サイトのドキュメントが秀逸なのでこの中身をご紹介いたします。

まずマルチページアプリケーションについてですが…

マルチページアプリケーション(MPA) とは、複数のHTMLページで構成されるWebサイトのことで、そのほとんどがサーバー上でレンダリングされます。新しいページに移動すると、ブラウザはサーバーに新しいページのHTMLを要求します。Astroは、MPAフレームワークの1つです。従来のMPAフレームワークには、Ruby on Rails、Python Django、PHP Laravel、WordPress、Joomla、Drupal、そしてEleventyやHugoなどの静的サイトジェネレーターも含まれます。

マルチページとはまぁ普通のWEBサイトも含まれますが、複数ページで構成されるあるWEBサイトですね。サーバーサイドレンダリング(SSR)と静的サイトジェネレーター(SSG)がこちらの陣営です。 続いて、SPAについてですが、

シングルページアプリケーション(SPA) とは、ユーザーのブラウザに読み込まれ、ローカルでHTMLをレンダリングする単一のJavaScriptアプリケーションで構成されるウェブサイトです。SPAもサーバー上でHTMLを生成することがありますが、SPAはブラウザ上でJavaScriptアプリケーションとしてウェブサイトを実行し、ページ遷移したときに同じHTMLで新しいHTMLのページを再描画する機能が特徴的です。Next.js、Nuxt、SvelteKit、Remix、Gatsby、Create React Appなどが、SPAフレームワークの一例として挙げられます。

とあります。 SPA は SSRと違い、ブラウザ上でHTMLを生成=レンダリングすることが大きな違いです。(個人的にはメインだった Angular がここに挙げられていないが非常に不満ではありますが。)

歴史的な経緯としては、

  1. ただのHTML
  2. SSR
  3. SPA
  4. SSG

でしょうか。ただのWEBサイトが動的なコンテンツを扱うようになり、サーバーの処理を軽減させるためにブラウザでHTMLを生成する方式と事前にHTMLを生成する方式が誕生してきました。 このような流れでSSRよりはSPAかSSGだよね、となりました。

Astro と他のMPAフレームワークの比較

公式サイトのページにはMPA vs SPAに引き続き “Astro vs 他のMPA” の記述もご紹介いたします。

Astroは、MPAフレームワークの1つです。しかし、Astroは他のMPAフレームワークとは一線を画しています。その大きな違いは、サーバー言語とランタイムにJavaScriptを使用している点です。従来のMPAフレームワークでは、サーバーに別の言語(RubyやPHPなど)を書き、ブラウザにはJavaScriptを書くことになります。Astroでは、常にJavaScriptとHTML、CSSを書くだけです。そうすれば、(ReactやSvelteのような)UIコンポーネントをサーバーとクライアントの両方でレンダリングできます。 その結果、Next.jsやその他のモダンなWebフレームワークとよく似た感覚で、より伝統的なMPAサイトアーキテクチャのパフォーマンス特性を備えた開発者体験が得られます。

ちなみに私はSSGとしてしか使っていませんが、Astro自体は SSG も SSR もできます。上記では JS と書いてますが、当然 Typescript も完全に対応してます。 サイト構築はTypescriptでやりたかったのでまずこれが1つのポイントとしてありました。

MPA vs. SPA

続いて “MPA vs SPA” の記述もあるのでご紹介いたします。

1. レンダリング

MPAでは、ページのHTMLのほとんどがサーバーでレンダリングされます。SPAでは、ブラウザ上でJavaScriptを実行することにより、ほとんどのHTMLがローカルにレンダリングされます。これは、サイトの動作、パフォーマンス、SEOに劇的な影響を与えます。

ブラウザでHTMLをレンダリングするのは、リモートサーバーにリクエストするよりも高速なオプションのように聞こえるかもしれません。しかし、これは正反対です。サーバーレンダリングを使用しない限り、SPAの最初のページ読み込み時のパフォーマンスは、MPAよりも常に遅くなります。これはSPAがページ上のHTMLをレンダリングするためだけに、ブラウザでJavaScriptアプリケーション全体をダウンロード、解析、実行する必要があるためです。さらに、SPAはリモートデータを取得する必要があるため、ページの読み込みが完了するまでに、もっと待ち時間がかかります。 (中略…) MPAはすべてのHTMLをリモートサーバーでレンダリングするため、多くの場合、(たとえあったとしても)JavaScriptの実行をあまり必要としません。このため、MPAはSPAよりも初回ロードがはるかに速く、コンテンツ重視のWebサイトには欠かせない存在です。しかし、これにはトレードオフがあります。将来のページ遷移ではローカルレンダリングの恩恵を受けられないため、最初のページロード以降、長期にわたるユーザー体験はそれほど得られないのです。

というわけでレンダリングのUXに関してはMPA方式のほうが若干、有利です。

2. ルーティング

Webサイトのルーターはどこに存在するのでしょうか。MPAでは、サーバーへのリクエストごとに、どのHTMLで応答するかを決定するため、ルーティング・ロジックはサーバーに格納されます。SPAでは、ルーターがブラウザでローカルに動作し、サーバーにアクセスすることなく新しいページをレンダリングするためにあらゆるナビゲーションをハイジャックします。

これは、前述のトレードオフと同様です。MPAは最初の読み込みが速く、SPAはJavaScriptアプリケーションがブラウザにすべて読み込まれると、2ページ目、3ページ目の読み込みが速くなる傾向にあります。

また、SPAはページレンダリングに関する多くの制御を行うため、ページナビゲーションでより強力なトランジション(遷移アニメーション)を提供できます。このサポートに対応するため、MPAはHotwireのTurboのようなツールを活用し、ブラウザのナビゲーションも制御してクライアントルーティングを模倣しています。HTMLは依然としてサーバーでレンダリングされますが、TurboはSPAのクライアントルーティングと同様に、ページ間のシームレスな遷移を表示できるようになりました。

ルーティングをどうするのか問題は非常に大きいです。クライアントサイドでルーティングを行うほうがWEBサーバーのパスをがんばるより遥かに細かい制御が可能です。

3. 状態管理

SPAは、複雑な複数ページの状態管理を扱うWebサイトのアーキテクチャとして優れています(例:Gmail)。これは、SPAがウェブサイト全体を単一のJavaScriptアプリケーションとして実行し、アプリケーションが複数のページにわたって状態とメモリを維持できるためです。受信トレイや管理者用ダッシュボードのようなインタラクティブでデータ駆動型のエクスペリエンスは、Webサイト自体が本質的に「アプリ的」であるため、SPAとしてうまく機能するのです。

サイトで一貫した状態管理を行うためには SPA が圧倒的に有利です。というか複数ページをまたぐセッション変数の管理は悪夢でした。

このようなわけで、MPA と SPA にはそれぞれ得意・不得意がありますが、最後の Webサイト自体が本質的に「アプリ的」である かどうかが最も大きなポイントではないでしょうか。 本サイトは初めからブログ記事メインのサイトを構築したいとの思いがあるので SPA のフレームワークは対象外、となりました。

Astro が決定的だった理由

上記の点で、おおむね Typescript で書ける MPA フレームワークってことなら Gatsby とかあるよね?となるかもしれませんが、Reactというコンポーネントにがっつり縛られる Gatsby ではちょっと…という点がありました。

まず、

Astroは、Webサイトを構築するために必要なものがすべて揃ったオールインワンのWebフレームワークです。 コンポーネント構文、ファイルベースのルーティング、アセットハンドリング、ビルドプロセス、バンドル、最適化、データフェッチなど、Astroにはさまざまな機能が搭載されています。Astroのコア機能だけで、優れたウェブサイトを構築できます。

という点で、がっつりUIコンポーネントを作りこまなくてもテンプレートとマークダウンだけでそこそこのウェブサイトが立ち上げられる、というのが嬉しかったです。(テンプレートもコンポーネントなんですが、まぁ。。。)

また固有のUIライブラリのカルチャをそのまま引きずっているのはいやだったのですが、その点で Astro とほかフレームワークの連携性がマッチしました。

AstroはUIにとらわれず、自分好みのUIフレームワークを持ち込めます(BYOF: Bring Your Own UI Framework)。React、Preact、Solid、Svelte、Vue、LitはすべてAstroで公式にサポートされています。同じページで異なるフレームワークを混在もでき、将来の移行を容易にし、単一のフレームワークにプロジェクトが固定されるのを防げます。

はい、ここです。UIフレームワークが選べる、ここが決定的でした。 本サイトではUIフレームワークの利用は最低限にしたい(というかSSG使うのでほとんどいらないはず)のであまり大掛かりなUIフレームワークは搭載したくありませんでした。

現時点ではいろいろ比較した結果、超軽量な Alpine.js を使っています。 Alpine.js については以下の記事もご覧ください!

まとめ

というわけで、Astro という SSG を選択した主なポイントは以下の通りです。

  • サイト全体がアプリ的ではない、コンテンツがメインのサイト
  • コンテンツの更新はビルド時だけでOK
  • Typescript が使える
  • 特定の UIフレームワークに依存しない。用途に応じてUIフレームワークが選べる。

実際、業務システム開発の現場業務で SSG は採用したことないです。 このサイトは自分がやったことのないフレームワークでサイトを構築してみる、というチャレンジもありましたがそもそも要件として実行時にサーバーにアクセスしてデータを取ってくる、という要件が必要のない、“ただのWEBサイト”である、ということが一番のポイントですね。

本家サイトのAstroの速度などについてはいろいろ上がっているようなのでご参考にしてみてはいかがでしょうか?

本日は以上です!

Astro.js、Tailwind CSSの入門にぜひ!