メインコンテンツへスキップ
#ツール比較 (更新 2026年7月17日) 約10分で読めます

Astro vs Next.js vs Hugo:静的サイトを2つAstroで運用している自分の選び方

ブログとポートフォリオをAstro 5で、案件管理アプリをNext.jsで実運用中の筆者が、SSG選びの実感を書く。Hugoを選ばなかった理由と、コンテンツはAstro・アプリはNext.jsという使い分けの根拠。

静的サイトジェネレーター(SSG)の比較記事は世の中に山ほどあるが、その多くは「全部良いところがあります」で終わる。自分はもう選び終わった側なので、この記事では結論から書く。コンテンツサイトはAstro、サーバーが要るアプリはNext.js。この使い分けで、いま実際に3つのプロジェクトを回している。

  • このブログ(clvr.lol): Astro 5。記事180本超をContent Collectionsで管理し、Cloudflare Pagesに静的配信。検索はPagefind
  • ポートフォリオサイト: Astro 5 + Tailwind CSS v4。VPSのnginxで静的ファイルをそのまま配信
  • 案件管理ダッシュボード: Next.js。DBを読み書きするのでNode.jsサーバーとして常駐

Hugoは候補に入れて検討したが採用しなかった。その理由も含めて、選定時に考えたことと、運用して初めてわかったことを書く。

なぜAstroを選んだか:書き味とContent Collections

最初にブログの技術選定をしたとき、比較したのはAstro・Next.js・Hugoの3つだった。Astroに決めた理由は大きく3つある。

1つ目はコンポーネントの書き味。 Astroの.astroファイルは、上半分にサーバーサイドのJS/TSを書いて、下半分にHTMLを書くだけの構造だ。

---
import { getCollection } from 'astro:content';
const posts = await getCollection('posts');
---

<ul>
  {posts.map(post => <li>{post.data.title}</li>)}
</ul>

ReactのようにuseStateやuseEffectを考える必要がなく、Hugoのように独自テンプレート構文を覚える必要もない。「JSで データを取ってきてHTMLに流し込む」という、静的サイトで本当にやりたいことがそのまま書ける。

2つ目はContent Collectionsの型検証。 記事のfrontmatterにZodスキーマを定義でき、違反するとビルドが落ちる。うちのブログではdescriptionは160字以内、categoryは6種のenumのみ、という制約を入れている。

これは運用してから効いてきた。うちは記事の一部をAIで自動生成しているので、規約外のfrontmatterが混入するリスクが常にある。実際、descriptionが160字を超えた記事やenum外のcategoryを持つ記事が生成されてビルドが落ちたことが何度かあるが、逆に言えば壊れた記事は本番に出る前に必ずビルドで止まる。記事が180本を超えた今、この検問なしの運用は考えられない。

3つ目はアイランドアーキテクチャ。 Astroはデフォルトでクライアントに一切JSを送らず、インタラクティブにしたい部分だけclient:loadなどで指定する。このブログには文字数カウントやJSON整形などのブラウザツールブラウザゲームがあるが、それらのページだけJSが載り、記事ページは素のHTMLのままだ。「基本は静的、一部だけ動く」という構成が、設計として最初から用意されている。

具体的な構築手順はこのブログを作ったときの記録に書いた。

Next.jsは「静的サイト用」としては選ばなかった。でもアプリでは使っている

Next.jsもSSGとして使える(generateStaticParamsで全ページを事前生成できる)が、ブログ用途では選ばなかった。理由は単純で、Reactランタイムを必要としないページにReactランタイムが付いてくるからだ。記事を読むだけのページに、hydration用のJSを送る意味がない。

一方で、副業の案件管理ダッシュボードはNext.jsで作った。こちらはSQLiteを読み書きし、案件のステータス更新や検索をリアルタイムにやる。つまりビルド時にHTMLを固められない。サーバーが常駐してリクエストごとに処理する前提のアプリで、これをAstroでやろうとすると結局SSRアダプタを入れてサーバーを立てることになり、Reactのエコシステム(UIライブラリ、フォーム処理)を素直に使えるNext.jsの方が速かった。

両方を運用して思うのは、AstroとNext.jsは競合というより守備範囲が違うということだ。よくある「Astro vs Next.jsどっちが良いか」という問いは、「出力が静的ファイルで完結するか、サーバーが要るか」を先に決めれば、ほぼ自動的に答えが出る。

  • ビルドしたら終わり、あとはCDNやnginxが配るだけ → Astro
  • リクエストのたびにDBを見る・認証する・書き込む → Next.js

うちのポートフォリオサイトはこの判断の極端な例で、Astroでnpm run buildしたdist/をVPSのnginx公開ディレクトリにコピーするだけで運用している。サーバープロセスなし、再起動なし、落ちる要素がない。静的サイトの利点はパフォーマンスの数字よりも、この「運用で考えることが消える」感覚の方が大きい。

Hugoを選ばなかった理由

正直に書くと、Hugoは本番運用したことがない。だからHugoの良し悪しを実感で語る資格はないが、「なぜ検討して外したか」は言える。

Hugoの武器はビルド速度で、Goのシングルバイナリが数千ページを数秒で処理するのはAstroには真似できない。記事が数千本あるメディアなら今でも有力だと思う。

自分が外した理由は2つ。1つはテンプレートがGoテンプレート構文で、普段書いているJS/TSの知識が活きないこと。もう1つは、ブラウザツールやゲームのようなJSが動くページを同じサイトに同居させたかったことだ。Hugoはコンテンツを高速にHTML化することに特化していて、そこにReactやフレームワークのコンポーネントを混ぜる設計にはなっていない。「記事も置くし、ツールも置くし、ゲームも置く」という雑食なサイトを1つのリポジトリでやるには、アイランドアーキテクチャのあるAstroの方が合っていた。

ちなみにAstroのビルド速度は、記事180本強の現状で困っていない。Cloudflare Pagesへのデプロイはビルド込みで数分あれば終わる。数千ページ規模になったら再評価するかもしれないが、個人〜中規模のサイトでビルド速度が決め手になることは、少なくとも自分の規模ではなかった。

運用してわかった、選定時には見えなかったこと

比較表を眺めていた頃には気づかなかったことをいくつか。

エコシステムの差は「困ったとき」に出る。 Astroは成長中とはいえNext.jsほどの情報量はなく、少しニッチなこと(Pagefindの組み込み方、Content Collectionsのスキーマ設計の細かい挙動など)は公式ドキュメントとGitHubのissueを直接読むことになる。ただ、静的サイトはそもそも複雑なことをしないので、困る頻度自体が低い。

型検証は「あとから」効く。 Content Collectionsのスキーマは、記事が10本の頃は正直ありがたみがなかった。180本を超えて、しかも生成を自動化した今、frontmatterの検問がビルドに組み込まれていることが品質の下限を支えている。SSGを選ぶとき「コンテンツが増えて管理が雑になったときに何が守ってくれるか」という観点は、比較記事にはあまり出てこないが実運用では重要だった。

パフォーマンスは黙っていても出る、が上限ではない。 AstroでJSゼロのページを作れば速いのは事実だが、画像やフォントの扱いを雑にすれば普通に遅くなる。実際にこのブログでもLCP改善のために手を入れた。そのあたりはCore Web Vitals改善の実践記録に書いている。

これから選ぶ人へ

自分の結論はシンプルだ。ブログ・ポートフォリオ・LP・ドキュメントのような「ビルドしたら静的ファイルで完結する」サイトならAstroを選ぶ。JS/TSの知識がそのまま使えて、Content Collectionsが後の自分を守ってくれて、必要になったらアイランドで動く部分を足せる。DBや認証が絡むアプリならNext.jsで、これは静的サイトジェネレーターの選定というより別の土俵の話。Hugoは記事数が数千本あってビルド速度が本当にボトルネックになるなら検討する、という位置づけにしている。

迷っているなら、まず作ろうとしているものが「ビルド後にサーバーが要るか」を紙に書いてみるといい。それが決まれば、フレームワークの比較表を眺める時間はほとんど要らなくなる。

#Astro #Next.js #Hugo #SSG #フレームワーク比較
シェア