Astro Prerenderで動的ルートを完全静的化する方法|SSG+動的パスでSEO最大化【2026年4月最新】
Astro 4.0以降のprerender機能で動的ルート([slug])を完全静的化し、SEO評価とパフォーマンスを両立する実装ガイド。getStaticPathsとの組み合わせを実例付きで解説。
Astroで動的ルート([slug].astro)を使うとき、「静的サイトとして生成したいのにビルド時に404エラーが出る」「動的ルートのSEOが不安」という悩みを抱えていませんか?
Astro 4.0以降、prerender機能とgetStaticPathsを組み合わせることで、動的ルートを完全に静的HTML化できるようになりました。これにより、ブログ記事やプロダクトページなど、URLパターンは動的だがコンテンツは事前に確定している場合に、完全な静的サイトとしてのSEO評価とパフォーマンスを実現できます。
この記事では、Astroの動的ルート静的化の仕組み、実装手順、ハマりやすい落とし穴までを、実際のコード例とともに解説します。
Astro Prerenderとは?動的ルートを静的化する仕組み
Astro 4.0(2023年12月リリース)以降、**export const prerender = true**というフラグがページ単位で使えるようになりました。これにより、ハイブリッドレンダリング構成(output: 'server' または output: 'hybrid')の中で、特定のページだけを静的生成(SSG)できます。
しかし、多くの開発者が見落としているのが、完全静的サイト(output: 'static')でも動的ルートには明示的な設定が必要という点です。
動的ルートの静的化に必要な2つの要素
flowchart LR
A["動的ルートファイル<br/>[slug].astro"] --> B["getStaticPaths()"]
B --> C["全URLパスを返す"]
C --> D["ビルド時に各HTMLを生成"]
D --> E["静的サイトとしてデプロイ"]
style A fill:#e1f5ff
style E fill:#d4edda
getStaticPaths()関数:ビルド時にどのパス(slug)を生成するか指定- propsを通じたデータ注入:各パスに対応するコンテンツをpropsとして渡す
この2つを正しく実装することで、/blog/article-1、/blog/article-2 のような動的パスがビルド時に個別の静的HTMLファイルとして生成されます。
実装手順:ブログ記事の動的ルートを完全静的化する
Step 1: プロジェクト構成の準備
src/
├── pages/
│ └── blog/
│ └── [slug].astro ← 動的ルート
├── content/
│ └── blog/
│ ├── article-1.md
│ ├── article-2.md
│ └── article-3.md
└── astro.config.mjs
Step 2: Content Collectionsの設定
Astro 4.xでは、Content Collectionsを使ってマークダウンファイルを管理するのがベストプラクティスです。
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string(),
publishedAt: z.date(),
tags: z.array(z.string()),
}),
});
export const collections = {
blog: blogCollection,
};
Step 3: 動的ルートでgetStaticPathsを実装
---
// src/pages/blog/[slug].astro
import { getCollection } from 'astro:content';
import type { GetStaticPaths } from 'astro';
// ビルド時に全記事のパスを生成
export const getStaticPaths = (async () => {
const blogEntries = await getCollection('blog');
return blogEntries.map(entry => ({
params: { slug: entry.slug },
props: { entry },
}));
}) satisfies GetStaticPaths;
// propsから記事データを受け取る
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{entry.data.title}</title>
<meta name="description" content={entry.data.description}>
<link rel="canonical" href={`https://example.com/blog/${entry.slug}`}>
</head>
<body>
<article>
<h1>{entry.data.title}</h1>
<time datetime={entry.data.publishedAt.toISOString()}>
{entry.data.publishedAt.toLocaleDateString('ja-JP')}
</time>
<Content />
</article>
</body>
</html>
Step 4: ビルド設定の確認
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
output: 'static', // 完全静的サイトとして生成
site: 'https://example.com', // canonicalタグ・サイトマップ用
});
ビルド結果の確認とSEOへの影響
静的HTMLの生成確認
ビルドを実行すると、以下のように各slugに対応するHTMLファイルが生成されます。
npm run build
dist/
└── blog/
├── article-1/
│ └── index.html
├── article-2/
│ └── index.html
└── article-3/
│ └── index.html
これにより、/blog/article-1 へのアクセスは静的HTMLとして即座に配信され、以下のSEO上の利点が得られます。
SEOパフォーマンスの改善指標
| 指標 | SSR/動的生成 | SSG(prerender) | 改善効果 |
|---|---|---|---|
| TTFB | 200-500ms | 10-50ms | 80-90%削減 |
| FCP | 1.5-3.0s | 0.5-1.0s | 60-70%短縮 |
| クローラー処理時間 | 変動あり | 安定して高速 | インデックス効率向上 |
| キャッシュ効率 | 低い | CDNで永続化可能 | 配信コスト削減 |
注: 上記の数値は一般的な実測値の範囲であり、実際の環境・コンテンツによって変動します
よくあるエラーと解決策
エラー1: getStaticPaths() が定義されていない
Error: getStaticPaths() function is required for dynamic routes.
原因: 動的ルート([slug].astro)でgetStaticPathsを実装していない
解決策: 上記Step 3のコードを参考に、必ずgetStaticPathsを実装する
エラー2: 一部のslugでビルドが失敗する
Error: [slug] does not match any static paths
原因: Content Collectionsのファイル名とslugが一致していない、またはフロントマターが不正
解決策:
- ファイル名を確認(例:
article-1.md→ slug:article-1) - schema検証エラーがないかログを確認
getCollection('blog', (entry) => !entry.data.draft)のようにフィルタリングしている場合、意図しない除外がないか確認
エラー3: propsがundefinedになる
const { entry } = Astro.props; // entry が undefined
原因: getStaticPathsでpropsを返していない
解決策:
return blogEntries.map(entry => ({
params: { slug: entry.slug },
props: { entry }, // ← これを必ず含める
}));
外部APIからデータを取得して静的化する
Content Collections以外に、外部API(HeadlessCMS、microCMS、Strapi等)からデータを取得して静的化することも可能です。
---
// src/pages/products/[id].astro
import type { GetStaticPaths } from 'astro';
export const getStaticPaths = (async () => {
// 外部APIから商品一覧を取得
const response = await fetch('https://api.example.com/products');
const products = await response.json();
return products.map((product: any) => ({
params: { id: product.id.toString() },
props: { product },
}));
}) satisfies GetStaticPaths;
const { product } = Astro.props;
---
<h1>{product.name}</h1>
<p>{product.description}</p>
<meta name="description" content={product.description}>
ビルド時の注意点
- APIレート制限に注意: 数百〜数千のパスを生成する場合、API呼び出しが制限に引っかかる可能性がある
- 環境変数の管理: APIキーは
.envファイルで管理し、.gitignoreに追加 - エラーハンドリング: API障害時にビルドが止まらないよう、フォールバック処理を実装
export const getStaticPaths = (async () => {
try {
const response = await fetch('https://api.example.com/products');
if (!response.ok) throw new Error('API fetch failed');
const products = await response.json();
return products.map(/* ... */);
} catch (error) {
console.error('Failed to fetch products:', error);
return []; // 空配列を返してビルドを継続
}
}) satisfies GetStaticPaths;
ハイブリッドレンダリングとの使い分け
Astro 4.5(2024年6月リリース)以降、output: 'hybrid' モードが強化され、動的ルートと静的ルートを同一プロジェクトで混在させやすくなりました。
graph TD
A["astro.config.mjs<br/>output: 'hybrid'"] --> B["デフォルト: SSR"]
B --> C["pages/blog/[slug].astro<br/>export const prerender = true"]
B --> D["pages/api/search.ts<br/>prerenderなし(動的)"]
C --> E["静的HTML生成"]
D --> F["リクエスト時に実行"]
style C fill:#d4edda
style D fill:#fff3cd
使い分けの基準
| ユースケース | 推奨モード | 理由 |
|---|---|---|
| ブログ記事、製品ページ | prerender: true | コンテンツが事前確定、SEO重視 |
| 検索API、フォーム送信 | SSR(prerenderなし) | リクエストごとに処理が変わる |
| ユーザーダッシュボード | SSR | 認証・個別データ表示が必要 |
| ランディングページ | prerender: true | 高速表示、CDNキャッシュ活用 |
まとめ
- Astroの動的ルート静的化には
getStaticPaths()が必須。これがないとビルドエラーになる - Content Collectionsを使えば、マークダウンファイルから自動的にパスを生成でき、型安全性も確保できる
- 外部APIからデータを取得する場合も、ビルド時に全パスを生成することで完全静的化が可能
- SEO上の最大の利点はTTFBの劇的な短縮(200-500ms → 10-50ms)とクローラーへの最適化
- ハイブリッドレンダリング(
output: 'hybrid')を使えば、静的ページと動的APIを同一プロジェクトで管理できる - エラーハンドリングとAPI制限を考慮し、大規模サイトでは段階的な生成戦略を検討する
動的ルートの静的化は、AstroのパフォーマンスとSEOを最大限に活かすための必須テクニックです。Content Collectionsとの組み合わせで、保守性の高い静的サイト構築を実現しましょう。