ヘッドレスCMSガイド

ヘッドレスCMSがよくわかる情報発信サイト

2025-04-30

高速な静的サイト構築の新定番!Astro (SSG) の特長・比較・使い方

高速な静的サイト構築の新定番!Astro (SSG) の特長・比較・使い方
Astroは、高い表示速度と優れた開発体験を両立させることで注目を集めている新しいWebフレームワークですが、 最近よく聞く『Astro』って、結局何がすごいの? Next.jsやNuxt、SvelteKitといった他のフレームワークと比べて、どう違うの? といった疑問や、フレームワーク選びの悩みをお持ちではありませんか? この記事では、Astroの特長や、主要フレームワークとの具体的な比較、そしてAstroの基本的な使い方までを徹底解説します。

Astroとは

Astroは、「より少ないJavaScriptで、より速いウェブサイトを構築する」ことを目指すモダンなフレームワークです。基本は静的サイトジェネレーター(SSG)として動作し、ビルド時に軽量なHTMLを生成することで高速表示を実現します。ReactやVueなどのフレームワークと組み合わせて利用可能で、SSRやハイブリッドレンダリングにも対応する柔軟性も持ち合わせています。

Astroの特長

表示速度を追求した設計思想

Astroが高速性を実現できる背景には、独自の設計思想といくつかの重要な特長があります。

デフォルトでゼロJavaScript

ビルド時に不要なJavaScriptを可能な限り削除し、ページの初期読み込みを高速化します。インタラクティブ性が必要な箇所にのみ、選択的にJavaScriptを適用します。

アイランドアーキテクチャ

ページ内のインタラクティブなUI要素(画像カルーセル、フォーム、ボタンなど)を「アイランド」として独立させます。各アイランドは分離して読み込まれるため、ページ全体のレンダリングを妨げることなく、リッチなUIと高速な表示を両立できます。

フレームワーク非依存

React、Vue、Svelte、Solidなどを同一プロジェクト内で自由に利用できます。

コンテンツ重視

MarkdownやMDXのサポートが手厚く、コンテンツの作成・管理が容易です。ファイルベースルーティングにより、直感的なサイト構造を構築できます。

レンダリングの柔軟性

静的サイト生成(SSG)に加え、サーバーサイドレンダリング(SSR)もサポート。サイトやページの要件に応じて最適なレンダリング方法を選択できます。

2025-04-30T08:16:24Z

Astro SSR 導入手順ガイド:基本解説から設定まで

これらの特徴により、開発者は優れた開発体験を得ながら、エンドユーザーには非常に高速なウェブサイトを提供することが可能になります。

主要フレームワークとの比較

多くのモダンなフレームワークがSSGをサポートしていますが、その実装方法や関連機能には違いがあります。今回は、SSGに対応した主要なフレームワーク(Astro、Next.js、Nuxt.js、Gatsby)を以下5つの項目で徹底比較します。

  • 学習コスト
  • 拡張性
  • ビルド時間
  • パフォーマンス
  • 向いているプロジェクト

Astro

学習コスト

低い。フレームワーク自体がシンプルで、SSGが基本。HTML/CSS/JavaScriptの基本知識があれば問題ありません。公式ドキュメントは質が高く、日本語翻訳も充実しています。

拡張性

SSGサイトにサーバー側の処理(APIルート)を追加して動的な機能を付与可能です。各種ツールやサービスとの連携機能も用意されています。

ビルド時間

SSGのビルドプロセスが効率的で高速です。大規模サイトでも速度が期待できます。

パフォーマンス

SSGによる高速な初期表示に加え、コンポーネントごとにJavaScriptを選択的に読み込む仕組みで不要なJavaScriptを削減するため、パフォーマンスが高いです。

向いているプロジェクト

ブログ、ドキュメント、ポートフォリオ、LPなど、パフォーマンスを重視するコンテンツ中心の静的サイト。インタラクティブ要素が少ない、または部分的に必要なサイトに有効です。

Next.js

学習コスト

やや高い。React知識に加え、ビルド時にデータを取得し動的なパスを持つページを生成する仕組みや、ビルド後にページを再生成する機能などの概念理解が必要です。公式ドキュメントは充実し日本語訳もありますが情報量が多いです。

拡張性

SSGサイトにAPIルートを追加してフルスタックな機能を実装可能です。ビルド後にページを再生成する機能により静的サイトの更新も可能です。Reactエコシステムを活用できます。

ビルド時間

SSG対象ページ数やデータ取得処理に依存し、大規模になると遅くなる傾向があります。CI/CDでのビルド時間も考慮が必要です。

パフォーマンス

SSGによるTTFB/LCP改善効果は高いです。画像最適化など機能も豊富にありますが、Reactベースのため、クライアントJavaScript量は多めとなります。インタラクティブになるまでの時間は他の軽量フレームワークに劣る可能性があります。

向いているプロジェクト

ブログ、企業サイト、ECサイトなどの比較的大規模で動的な要素も含む静的サイトに向いています。コンテンツ鮮度維持機能が必要な場合や、API連携も重視するプロジェクトなど。

Nuxt.js

学習コスト

やや高い。Vue経験者であればフレームワークの規約や追加機能を学ぶことで比較的スムーズに移行できますが、未経験者の場合はVue自体の学習コストも加わります。ドキュメントは充実し日本語訳もあり学習リソースは豊富です。

拡張性

SSGサイトにサーバー機能を提供するエンジンによりAPIルートやサーバー処理を簡単に追加可能です。また、Vueエコシステムのモジュールによる拡張も可能です。

ビルド時間

Nuxt 3と新しいビルドツールにより、以前より改善され良好です。

パフォーマンス

SSGによる高速表示に加え、Vue 3のパフォーマンス、データとHTMLを分離して最適化する仕組み、コード分割などの最適化が効きます。クライアントJavaScript量はNext.jsより少ない傾向にあります。

向いているプロジェクト

ブログ、企業サイト、ドキュメントなどの静的サイト全般に向いています。API機能も統合したい場合や、Vueエコシステムを活用したいプロジェクトなど。

Gatsby

学習コスト

高い。React知識に加え、GraphQLを用いたデータ管理の仕組みやビルドプロセスをカスタマイズするAPIの理解が必要です。日本語ドキュメントは限定的で、学習のハードルが高いです。

拡張性

拡張機能によるデータソース連携や機能追加は豊富にあります。サーバーレス機能も追加可能です。

ビルド時間

SSGのビルド時間が遅いことが欠点となります。大規模サイトでは実用的でない場合が多いです。

パフォーマンス

ビルド時に多くの最適化を行うため、生成されたサイトのランタイムパフォーマンス(特に画像)が高いです。

向いているプロジェクト

多数のデータソース(Markdown含む)をGraphQLで扱いたい、かつビルド時間を許容できる静的サイト。ブログ、ドキュメントなどに向いています。

比較まとめ

学習しやすく、速いパフォーマンスとビルド速度を求めるなら ⇒ Astro
既存のReact、Vueスキルを活用し、高い拡張性を求めるなら ⇒ Next.js、Nuxt.js
速いパフォーマンスと多数のデータソースをGraphQLで扱いたいなら ⇒ Gatsby

各フレームワークのSSGにおける特性を理解し、プロジェクトの要件やチームの状況に合わせて最適なものを選びましょう。

Astroの使い方

はじめに:環境構築

Node.js をインストール

Node.js は Astro を動かすために必要です。
もしまだインストールしていない場合は、Node.js公式サイト からLTS版(推奨版)をダウンロードしてインストールしてください。ターミナル(WindowsならコマンドプロンプトやPowerShell、Macならターミナル.app)で node -v と入力し、バージョンが表示されればOKです。

Asrtro プロジェクトの作成

ターミナルを開き、下記コマンドを実行してプロジェクトを作成します。

# npmを使う場合
npm create astro@latest

# yarnを使う場合
yarn create astro

# pnpmを使う場合
pnpm create astro

対話式でインストールを進めます。

Where should we create your new project?
(新しいプロジェクトはどこに作成しますか?)
> プロジェクト名を入力(ここでは my-astro-site と入力)

How would you like to start your new project?
(新しいプロジェクトをどのように開始しますか?)
> Use minimal (empty) template(最小限のテンプレート)を選択

Install dependencies?
(依存関係をインストールしますか?)
> Yes を選択

Initialize a new git repository? (optional)
(新しいGitリポジトリを初期化しますか?(任意))
> 一緒にリポジトリを作成したいなら Yes を選択、必要ない or 既にあるなら No を選択

これで新しいプロジェクトが作成されました。

開発サーバーを起動する

プロジェクトが作成できたら、実際にブラウザで表示を確認しながら開発を進められるように、「開発サーバー」を起動します。
ターミナルで、先ほど作成したプロジェクトフォルダに移動します。
(my-astro-site には先ほど命名したプロジェクト名を入れてください)

cd my-astro-site

以下のコマンドを実行し、開発サーバーを起動します。

# npmを使う場合
npm run dev

# yarnを使う場合
# yarn dev

# pnpmを使う場合
# pnpm dev

ターミナルに Local: の後にURL(例: http://localhost:4321/など)が表示されたら成功です。そのURLをコピーしてWebブラウザで開いてみてください。

(上記のようなAstroの初期画面が表示されます)

これで、ファイルを変更すると自動的にブラウザ表示が更新される状態になりました。ターミナルはこのまま起動しておいてください。

ディレクトリ構造

基本的なディレクトリ構造は以下のような形になります。

public/          - astroで処理されない静的アセット(画像、アイコンなど)
src/ - プロジェクトソースコードディレクトリ
components/ - コンポーネント用ディレクトリ
layouts/ - 共通レイアウト用ディレクトリ
pages/ - ルーティング用ディレクトリ
astro.config.mjs - Astroの設定ファイル

ページ作成とルーティング

Astroプロジェクトの中心となるのが src/pages/ ディレクトリです。このディレクトリに置かれた .astro, .md, .mdx, .html ファイル、あるいはサポートされているフレームワークコンポーネント(.jsx, .tsx など、別途インテグレーションが必要)は、自動的にサイトのページとして扱われます。

基本的なページ

トップページ src/pages/index.astro を作成します。

---
// ここはフロントマターと呼ばれ、JavaScriptコード(コンポーネントスクリプト)を書く
// ことができます。

//src/pages/index.astro

const pageTitle = 'ホームページ';
---
<html lang='ja'>
<head>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width' />
<title>{pageTitle}</title>
</head>
<body>
<h1>{pageTitle}</h1>
<p>Astroへようこそ!</p>
</body>
</html>

アバウトページ src/pages/about.astro を作成します。

---
// ここはフロントマターと呼ばれ、JavaScriptコード(コンポーネントスクリプト)を書く
// ことができます。

//src/pages/about.astro

const pageTitle = '私たちについて';
---
<html lang='ja'>
<head>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width' />
<title>{pageTitle}</title>
</head>
<body>
<h1>私たちについて</h1>
<p>これはアバウトページです。</p>
<a href='/'>ホームへ戻る</a>
</body>
</html>

これらを保存すると、すぐに http://localhost:4321/ や http://localhost:4321/about にアクセスして確認することができます。

ネストされたルート

ディレクトリ構造を使って、より整理されたURLパスを作成できます。
以下のようなファイルを作成した場合、ディレクトリ構造がそのままサイトのURL構造に対応します。

ブログ一覧ページ src/pages/blog/index.astro を作成します。
個別のブログ記事ページ src/pages/blog/my-first-post.astro を作成します。

src/
└── pages/
├── index.astro -> /
├── about.astro -> /about
└── blog/
├── index.astro -> /blog または /blog/
└── my-first-post.astro -> /blog/my-first-post

動的ルート

ブログ記事や商品詳細ページのように、URLの一部が可変になるページを作成したい場合があります。Astroでは、ファイル名に [] (角括弧) を使うことで 動的ルート を定義できます。

src/pages/posts/[slug].astro というファイルを作成すると、/posts/hello-world, /posts/learning-astro, /posts/anything-else のようなURLにマッチするページを1つのファイルで処理できます。

[slug] (角括弧)で囲まれた部分は パラメータ と呼ばれ、任意の名前(ここではslug)を付けられます。
.astro ファイルのフロントマター内で Astro.params オブジェクトを使うと、URLからパラメータの値を取得できます (例: /posts/hello-world なら Astro.params.slug は 'hello-world' になります)。

---
// ここはフロントマターと呼ばれ、JavaScriptコード(コンポーネントスクリプト)を書く
// ことができます。

// src/pages/posts/[slug].astro

const { slug } = Astro.params; // URLからパラメータを取得
---
<html lang='ja'>
<head>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width' />
<title>{pageTitle}</title>
</head>
<body>
<h1>記事スラッグ: {slug}</h1>
<a href='/posts/'>記事一覧へ</a>
</body>
</html>

レストパラメータ

URLの複数のセグメントにマッチさせたい場合、ファイル名に [...param] (角括弧と3つのドット) を使う レストパラメータ を利用できます。

src/pages/files/[...path].astro というファイルを作成すると、以下のようなURLすべてにマッチします。

/files/a/b/c.txt
/files/documents/report.pdf
/files/image.jpg

マッチしたパス部分はAstro.params.pathで取得することができます。もしルート (/files/) にマッチした場合、Astro.params.path は undefined になります。

---
// src/pages/files/[...path].astro

// URLからパス部分を取得
// 例: /files/a/b/c なら Astro.params.path は 'a/b/c'
const { path } = Astro.params;
---
<html lang='ja'>
<head>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width' />
<title>{pageTitle}</title>
</head>
<body>
<h1>ファイルパス</h1>
<p>{path ? `要求されたパス: /files/${path}` : 'ファイルルート /files/'}</p>
{/* ここでファイルの内容を表示するなどの処理 */}
</body>
</html>

ルートの優先順位

もし同じURLに複数のルートがマッチする可能性がある場合、Astroは以下の優先順位でルートを選択します。

  • 静的ルート (例: index.astro, about.astro) - 最も優先度が高い
  • 動的ルート (例: [slug].astro)
  • レストパラメータ (例: [...path].astro) - 最も優先度が低い

レイアウト機能

Webサイトを構築する際、多くのページでヘッダー、フッター、ナビゲーションメニュー、基本的なHTML構造(<html>, <head>, <body> タグなど)といった共通の要素が必要になります。これらの要素をすべてのページにコピー&ペーストするのは非効率で、後で修正が必要になった場合に大変な手間がかかります。

Astroの レイアウト機能 は、このような問題を解決するための仕組みです。レイアウトコンポーネントを使うことで、共通のUI構造を一度定義し、複数のページで簡単に再利用できます。

基本的なレイアウト

レイアウトは一般的に src/layouts/ ディレクトリを使用します。

ここでは src/layouts/BaseLayout.astro というファイルを作成します。

---
// ここはフロントマターと呼ばれ、JavaScriptコード(コンポーネントスクリプト)を書く
// ことができます。

// Propsを受け取るための定義(ページのタイトルを渡せるようにする)
interface Props {
title: string;
}
const { title } = Astro.props;
---
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width'>
<title>{title} - Astroテストサイト</title>
</head>
<body>
<header>
<nav>
<a href='/'>ホーム</a> <a href='/about'>私について</a>
</nav>
</header>
<main>
<slot />
</main>
<footer>
&copy; {new Date().getFullYear()} Astroテストサイト
</footer>
</body>
</html>

コードの中に<slot /> タグがあります。これがレイアウト機能の核となる要素です。この場所に、レイアウトを使用するページコンポーネントのコンテンツ(子要素)が挿入されます。

ページからレイアウトを利用する
作成したレイアウトコンポーネントをページ(src/pages/ 内のファイル)から利用する方法は簡単です。
ページコンポーネントのフロントマターで、利用したいレイアウトコンポーネントを import します。
ページのコンテンツ全体を、インポートしたレイアウトコンポーネントのタグで囲みます。
レイアウトが必要とするプロパティ(例: title)を渡します。

前ステップで作成した src/pages/index.astro を修正してみましょう。

---
// ここはフロントマターと呼ばれ、JavaScriptコード(コンポーネントスクリプト)を書く
// ことができます。

//src/pages/index.astro

import BaseLayout from '../layouts/BaseLayout.astro'; // レイアウトをインポート

const pageTitle = 'ホームページ';
---
<BaseLayout title={pageTitle}> {/* レイアウトで囲み、titleを渡す */}
<h1>{pageTitle}</h1>
<p>Astroへようこそ!</p>
</BaseLayout>

これで<BaseLayout>で囲まれた部分がページとして読み込まれ、BaseLayoutで定義された共通のヘッダー、フッターを持つようになります。

コンポーネント機能

Webサイトやアプリケーションを開発していると、ボタン、カード、ナビゲーションバー、フォーム要素など、繰り返し使われるUIパーツがたくさん出てきます。これらをその都度記述するのは非効率で、デザインや機能の変更があった場合にすべての箇所を修正するのは大変です。


Astroの コンポーネント は、UIを再利用可能な独立した部品に分割するための仕組みです。コンポーネントを使うことで、コードが整理され、開発効率とメンテナンス性が大幅に向上します。
(レイアウト機能もコンポーネントの一種です)

基本的なコンポーネント

コンポーネントは一般的に src/components/ ディレクトリを使用します。
例としてここでは src/components/HelloName.astro というファイルを作成します。

---
// src/components/HelloName.astro

interface Props {
name: string; // 'name' という文字列型のプロパティを受け取ることを定義
}

// Astro.props から 'name' プロパティを取得
const { name } = Astro.props;
---
<div>
<p>こんにちは、{name}さん!</p> {/* 受け取った name を表示 */}
</div>

<style>
/* このコンポーネント専用のスタイル */
p {
color: rebeccapurple;
font-weight: bold;
}
</style>

src/pages/index.astro でコンポーネントを使う

---
// ここはフロントマターと呼ばれ、JavaScriptコード(コンポーネントスクリプト)を書く
// ことができます。

//src/pages/index.astro

import BaseLayout from '../layouts/BaseLayout.astro'; // レイアウトをインポート
import HelloName from '../components/HelloName.astro'; // HelloNameコンポーネントをインポート

const pageTitle = 'ホームページ';
---
<BaseLayout title={pageTitle}> {/* レイアウトで囲み、titleを渡す */}
<h1>{pageTitle}</h1>
<p>Astroへようこそ!</p>

<HelloName name='あなた' />
</BaseLayout>

これで HelloName コンポーネントで定義された挨拶メッセージが表示されます。

Props(プロパティ)

Props は、親コンポーネント(呼び出し元)から子コンポーネントへデータを渡すための仕組みです。コンポーネントを再利用可能にするための重要な要素です。

渡し方は、HTMLの属性のように

<ComponentName propName={value} />

と記述します。
文字列は

<ComponentName propName='value' />

のように渡します。

受け取り方は、コンポーネントのフロントマター内で Astro.props オブジェクトから分割代入などで受け取ります (const { propName } = Astro.props;)。

TypeScriptを使用している場合、interface Props { ... } のように型を定義することで、どのようなPropsを受け取るか、型は何かを明確にし、エディタの補完や型チェックの恩恵を受けられます。

CSSスタイル適用方法

Astroは、開発者が好みの方法でスタイルを適用できるよう、非常に柔軟なアプローチを提供しています。コンポーネントごとに独立したスタイルを定義したり、サイト全体に共通のスタイルを適用したり、人気のCSSフレームワークと統合したりすることが可能です。

スコープスタイル

最も基本的で推奨される方法は、.astro ファイル内に直接 <style> タグを記述することです。

---
// ここはフロントマターと呼ばれ、JavaScriptコード(コンポーネントスクリプト)を書く
// ことができます。

//src/pages/index.astro

import BaseLayout from '../layouts/BaseLayout.astro'; // レイアウトをインポート
import HelloName from '../components/HelloName.astro'; // HelloNameコンポーネントをインポート

const pageTitle = 'ホームページ';
---
<BaseLayout title={pageTitle}> {/* レイアウトで囲み、titleを渡す */}
<h1>{pageTitle}</h1>
<p>Astroへようこそ!</p>

<HelloName name='あなた' />
</BaseLayout>

<style>
/* このスタイルはこのファイルの要素にのみ適用されます */
h1 {
font-size:32px;
margin-bottom:40px;
}
p {
font-size:16px;
font-weight: bold;
color: #666;
margin: 0;
}
</style>

Astroの <style> タグは、デフォルトで スコープ化 されています。これは、<style> 内に書かれたCSSルールが、そのファイル内のHTML要素にのみ適用され、他のコンポーネントやグローバルなスタイルに影響を与えない(または影響を受けない)ことを意味します。

Astroはビルド時に、一意なクラス属性(例: astro-XXXXXX)を追加し、CSSセレクタもそれに対応するように変換することで、このスコープ化を実現します。

グローバルスタイル

サイト全体に共通のスタイル(例: CSSリセット、基本的なタイポグラフィ、HTML要素のデフォルトスタイル)を適用したい場合もあります。Astroではいくつかの方法があります。

方法1:is:global
特定のコンポーネント(通常は共通のレイアウトコンポーネントなど)内で、グローバルなスタイルを定義したい場合は、<style> タグに is:global 属性を追加します。

---
// src/layouts/BaseLayout.astro
// ... 省略 ...
---
<html>
<head>
{/* ... 省略 ... */}
</head>
<body>
<slot />
</body>
</html>

<style is:global>
/* このスタイルはサイト全体に適用されます */
body {
font-family: 'Noto Sans JP', sans-serif;
margin: 0;
padding: 1em;
background-color: #f8f8f8;
}

h1, h2, h3 {
color: #333;
}

a {
color: dodgerblue;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>

is:global を使うとスコープ化が無効になるため、セレクタの衝突に注意が必要です。影響範囲を理解した上で、限定的に使用しましょう。

方法2:外部CSSファイルのインポート
グローバルCSSルールを別の .css ファイルに記述し、それを共通のレイアウトコンポーネントなどで import することです。

ここでは src/styles/global.css を作成します。

/* src/styles/global.css */
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap');

body {
font-family: 'Noto Sans JP', sans-serif;
margin: 0;
padding: 1em;
background-color: #f8f8f8;
}
/* ... 他のグローバルスタイル ... */

作成したCSSファイルを src/layouts/BaseLayout.astro のフロントマターでインポートします。

---
// src/layouts/BaseLayout.astro

import '../styles/global.css'; // CSSファイルをインポート

// ... 省略 ...
---
<html>
<head>
{/* ... 省略 ... */}
</head>
<body>
<slot />
</body>
</html>

この方法の利点は、CSSファイルがAstroのビルドプロセスによって処理され、最適化(不要なコードの削除や圧縮など)の対象となることです。

まとめ

この記事では新世代フレームワークAstroについて、そのユニークな特長から、主要フレームワークとの比較、そして実際にサイトを構築するための基本的な使い方までを解説してきました。

しかしAstroのポテンシャルはまだまだ広がっています。サーバーサイドレンダリング(SSR)、APIルートの作成、コンテンツコレクションによる効率的なコンテンツ管理、豊富なインテグレーションなど、探求すべき機能は数多く存在します。ぜひ充実した公式ドキュメントを確認してAstroの可能性をさらに引き出してみてください。

フェンリル株式会社

ヘッドレスCMS「NILTO」