ここまで出来る!Astro.jsルーティングの基本と動的ルート実装

※本ページはプロモーションを含みます

Web開発のフロントエンド技術は急速に進化し、開発者はより高速で柔軟なツールを求めています。その中で注目を集めているのが Astro です。Astroは、静的サイトジェネレーターの一種でありながら、動的コンテンツも扱える柔軟性を持つフレームワークです。特に、静的サイトの構築に最適化されており、軽量かつ高速なWebページを提供できる点が特徴です。

本記事では、Astroのルーティング に焦点を当て、その基本概念から実践的な実装方法まで詳しく解説します。ルーティングとは、ユーザーが特定のURLにアクセスした際に、どのページを表示するのかを決定する仕組みのことを指します。Astroでは、シンプルなファイルベースのルーティングを採用しており、直感的で管理しやすいのが魅力です。

また、本記事では以下の点について詳しく説明します。

記事のポイント

  • Astroのルーティングの基本概念と種類
  • 静的ルーティングと動的ルーティングの違い
  • 実際の実装例(getStaticPathsの活用、ページネーション、パンくずリスト、APIルートなど)

これからAstroを使ってWebサイトを開発しようと考えている方や、ルーティングの設定方法を詳しく知りたい方にとって、本記事が実践的なガイドとなることを目指します。それでは、まずはAstroのルーティングの基本から見ていきましょう。

▼Astroの概要については別の記事で紹介しています。
なぜ使わないの?Astroでモダン&最速のWebサイト構築!

▼Astroの公式サイトはこちら
https://astro.build/

1. Astro.js ルーティングの基本

Astroのルーティングは、ファイルベースルーティングを採用しており、プロジェクト内の src/pages フォルダに配置されたファイルの構造が、そのままURLパスとしてマッピングされます。これにより、ルーティングの設定が直感的でわかりやすくなっているのが特徴です。

例えば、以下のようなディレクトリ構造があった場合、それぞれのページは次のようなURLになります。

/src/pages/
  ├── index.astro      → https://example.com/
  ├── about.astro      → https://example.com/about
  ├── blog/
  │   ├── index.astro  → https://example.com/blog/
  │   ├── post1.astro  → https://example.com/blog/post1
  ├── contact.astro    → https://example.com/contact

このように、フォルダとファイルの構成がそのままURLに反映されるため、特別な設定をしなくても、シンプルなルーティングを構築できます。

1-1. ルーティングの種類

Astroには、主に以下の3種類のルーティングが存在します。

  1. 静的ルーティング: 固定されたページに対応するルーティング(例:about.astro/about
  2. 動的ルーティング: パラメータを含むルーティング(例:[id].astro/blog/:id
  3. APIルート: Astroファイルではなく、APIエンドポイントとして機能するルート(例:api/data.ts/api/data

次のセクションでは、これらのルーティングの詳細について解説していきます。

1-2. 静的ルーティング

静的ルーティングとは、あらかじめ決まったURLに対して特定のページを割り当てる方式です。Astroでは、src/pages フォルダ内のファイル構造がそのままURLに対応するため、特別な設定をしなくても、ページを作成するだけでルーティングが機能します。

基本的な静的ルートの作成

例えば、以下のようなページファイルを作成すると、対応するURLが自動的に生成されます。

/src/pages/
  ├── index.astro      → https://example.com/
  ├── about.astro      → https://example.com/about
  ├── services.astro   → https://example.com/services

about.astro のファイル内容は以下のようになります。

---
const title = "About";
---

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>{title}</title>
</head>
<body>
	<header>共通ヘッダー</header>	
	<main>
		<h1>{title}</h1>
		<p>私たちの会社について紹介します。</p>
	</main>
	<footer>共通フッター</footer>
</body>
</html>

このように、Astroでは .astro ファイルを作成するだけで、URLが自動的に割り当てられます。

ネストされたページ

ディレクトリを使ってページをネストすることもできます。例えば、以下のような構造の場合:

/src/pages/
  ├── index.astro         → /
  ├── blog/
  │   ├── index.astro     → /blog/
  │   ├── post1.astro     → /blog/post1
  │   ├── post2.astro     → /blog/post2
  ├── contact.astro       → /contact

この場合、/blog/post1 のようなURLが自動的に作成されます。

レイアウトの適用

Astroでは、複数のページで共通のレイアウトを適用することも可能です。例えば、src/layouts/BaseLayout.astro を作成し、各ページに適用できます。

---
const { title } = Astro.props;
---

<!doctype html>
<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>{title}</title>
	</head>
	<body>
		<header>共通ヘッダー</header>
		<main>
            <slot />
        </main>
		<footer>共通フッター</footer>
	</body>
</html>

そして、about.astro でこのレイアウトを使用するには以下のように記述します。

---
import BaseLayout from "../layouts/BaseLayout.astro";
const title = "About";
---

<BaseLayout title={title}>
	<h1>{title}</h1>
	<p>私たちの会社について紹介します。</p>
</BaseLayout>

<BaseLayout></BaseLayout> で囲まれた内容がBaseLayout.astroファイル内の <slot /> 部分に出力されます。

これにより、BaseLayout.astro の共通レイアウトを活用しながら、個々のページのコンテンツを管理できます。

静的ルーティングは、Astroのルーティングの中でも最も基本的で直感的な方法です。次のセクションでは、動的ルーティングについて詳しく解説していきます。

1-3. 動的ルーティング

静的ルーティングでは、各ページが固定のURLに対応していましたが、動的ルーティングを使用すると、パラメータを含むURL を設定できます。これにより、ブログ記事の詳細ページやユーザープロフィールページなど、コンテンツごとに異なるページを動的に生成することが可能になります。

動的ルーティングの基本

Astroでは、[パラメータ名].astro という命名規則を使うことで、URLの一部を動的に扱うことができます。たとえば、ブログ記事ごとに異なるURLを持つページを作成する場合、以下のような構造になります。

/src/pages/
  ├── index.astro        → /
  ├── blog/
  │   ├── [slug].astro   → /blog/:slug

この場合、/blog/post1/blog/post2 など、異なる slug 値を持つURLが動的に生成されます。

動的ルートの実装

src/pages/blog/[slug].astro を作成し、以下のように記述します。

---
export function getStaticPaths() {
	return [
		{ params: { slug: 'post' } },
		{ params: { slug: 'astro-routing' } },
	];
}
const { slug } = Astro.params;
---
<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<title>ブログ記事:{ slug }</title>
	</head>
	<body>
		<h1>ブログ記事:{ slug }</h1>
		<p>この記事のスラッグは「{ slug }」です。</p>
	</body>
</html>

このページにアクセスすると、URLの slug に応じて異なるコンテンツが表示されます。

例えば:

  • /blog/postslug = "post"
  • /blog/astro-routingslug = "astro-routing"

getStaticPathsの処理部分は動的ルーティングには必須の処理になります。ここが未設定の場合はエラー画面が表示されます。

開発系のエラーメッセージ。動的ルーティングには必須です

例えば、ブログ記事のリストが src/content/blog.json に保存されているとします。

クエリパラメータとの違い

動的ルーティングは、クエリパラメータ(?id=123 など)とは異なり、SEOの観点でより適切なURL構造を提供できます。例えば:

手法URL 例特徴
クエリパラメータ/blog?slug=post1SEO的に不利、キャッシュ効率が悪い
動的ルーティング/blog/post1SEOに有利、URLが簡潔でわかりやすい

そのため、SEOを意識したサイト構築では動的ルーティングを活用するのが望ましいです。

動的ルーティングを活用することで、パラメータを利用した柔軟なページ作成が可能になります。次のセクションでは、具体的なルーティング設定の実例として、getStaticPaths の詳細、ページネーション、パンくずリストの実装 について解説します。

2. Astro.js ルーティングの設定実例

2-1. getStaticPaths の活用方法

getStaticPaths は、Astroの静的サイト生成機能の一部で、動的ルートを持つページをビルド時に事前生成する ために使用されます。特に、ブログ記事や商品ページなどの個別ページを静的に作成する際に不可欠な機能です。

getStaticPaths の基本

動的ルーティング ([slug].astro) を使用する場合、AstroはそのページをどのURLで生成すればよいかを知る必要があります。getStaticPaths を定義することで、Astroはページごとのパスを取得し、ビルド時に静的なHTMLファイルを生成できます。

基本的な構文

---
// getStaticPaths関数を定義
export async function getStaticPaths() {
	return [
		{ params: { slug: 'post1' } },
		{ params: { slug: 'post2' } },
	];
}

// ルートパラメータを取得
const { slug } = Astro.params;
---
<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<title>ブログ記事:{ slug }</title>
	</head>
	<body>
		<h1>ブログ記事:{ slug }</h1>
		<p>この記事のスラッグは「{ slug }」です。</p>
	</body>
</html>

この例では、/blog/post1/blog/post2 の2つのページが事前に生成されます。

逆に言うとgetStaticPaths関数に設定していないスラッグ(post1とpost2以外)はエラーになります。

外部データを使用した動的ルートの生成

実際のプロジェクトでは、データをJSONやCMS(Contentful、WordPress、microCMSなど)から取得してルートを作成することが多いです。例えば、JSONデータを元に getStaticPaths を設定すると、以下のようになります。

データ(src/content/blog.json

[
  { "slug": "astro-intro", "title": "Astro入門" },
  { "slug": "routing-guide", "title": "ルーティング完全ガイド" }
]

動的ルート(src/pages/blog/[slug].astro

---
import blogData from "../../content/blog.json";

// getStaticPaths で動的にルートを生成
export async function getStaticPaths() {
	return blogData.map((post) => ({
		params: { slug: post.slug },
	}));
}

const { slug } = Astro.params;
const post = blogData.find((post) => post.slug === slug);
---

<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<title>{ post?.title }</title>
	</head>
	<body>
		<h1>{ post?.title }</h1>
		<p>この記事のスラッグは「{ slug }」です。</p>
	</body>
</html>

この設定により、blog.json に記述された記事が自動的に静的ページとして生成されます。

補足:「post?.title」の「?」って何?

コードの post?.title にある ?オプショナルチェイニング(Optional Chaining) という記法です。postnull または undefined の場合にエラーを防ぐためのものです。

getStaticPaths のメリット

  • SEOの向上 クエリパラメータを使う場合と比べ、Googleの検索エンジンが適切にページをインデックスしやすくなります。
  • ページの高速化 事前にHTMLを生成するため、サーバー負荷が減り、ページの表示速度が向上します。
  • CDNキャッシュの活用 静的ファイルとしてデプロイされるため、CDN(Content Delivery Network)をフル活用できます。

getStaticPaths を使うべきケース

ケースgetStaticPaths の使用
ブログ記事一覧から詳細ページを生成必須
商品一覧から個別商品ページを生成必須
固定ページ(about, contact など)不要
ユーザーが動的に生成するページ(例: リアルタイム検索結果)不適切

getStaticPaths を活用することで、Astroの静的ルーティングを最大限に活かすことができます。次のセクションでは、実践的な応用として、ページネーション(3-2) の実装について解説します。

2-2. ページネーションの実装例

ページネーション(ページ分割)は、ブログ記事や商品リストなどの大量のコンテンツを、複数のページに分けて表示する ための仕組みです。Astroでは、getStaticPaths を活用することで、静的にページネーションを実装 できます。

ページネーションの基本概念

一般的に、ページネーションは次のような構造を持ちます。

  • 1ページに 5記事 表示する場合
  • 記事が合計 12件 ある場合
  • 3ページに分割される
    • /blog/(1ページ目: 記事 1~5)
    • /blog/page/2(2ページ目: 記事 6~10)
    • /blog/page/3(3ページ目: 記事 11~12)

Astroでは、各ページを静的に生成し、ページ間を移動できる 「前へ」「次へ」ナビゲーション を追加することで、直感的な操作が可能になります。

ページネーションの実装

1. データ(src/content/blogPosts.json

まず、ブログ記事のデータを用意します。

[
  { "slug": "astro-intro", "title": "Astro入門" },
  { "slug": "routing-guide", "title": "ルーティング完全ガイド" },
  { "slug": "static-site", "title": "静的サイトの作り方" },
  { "slug": "seo-tips", "title": "SEOの基本" },
  { "slug": "web-performance", "title": "Webサイトの高速化" },
  { "slug": "ssr-vs-ssg", "title": "SSR vs SSGの違い" },
  { "slug": "component-design", "title": "コンポーネント設計" }
]

記事数が7件なので、1ページに3件ずつ 表示するページネーションを作成します。

2. getStaticPaths を使ったページネーション(src/pages/blog/page/[page].astro

---
import blogData from "../../../content/blog.json";

// 1ページあたりの表示数 
// ▼【誤】下記はエラー※Astroのファイルスコープ外で定義すると、getStaticPaths内で参照できない
// const POSTS_PER_PAGE = 3;
// ▼【正】グローバルスコープで明示的に定義することでgetStaticPaths内で参照できるようになる
export const POSTS_PER_PAGE = 3;

// ページネーションのための静的ルート生成
export async function getStaticPaths() {
  const totalPages = Math.ceil(blogData.length / POSTS_PER_PAGE);
  return Array.from({ length: totalPages }).map((_, i) => ({
    params: { page: String(i + 1) },
  }));
}

// 現在のページ番号を取得
const { page } = Astro.params;
const currentPage = Number(page);

// 表示する記事を取得
const startIndex = (currentPage - 1) * POSTS_PER_PAGE;
const endIndex = startIndex + POSTS_PER_PAGE;
const posts = blogData.slice(startIndex, endIndex);

// 前後のページリンクを作成
const prevPage = currentPage > 1 ? `/blog/page/${currentPage - 1}` : null;
const nextPage = endIndex < blogData.length ? `/blog/page/${currentPage + 1}` : null;
---
<html lang="ja">
  <head>
		<meta charset="UTF-8" />
    <title>ブログ一覧 - ページ {page}</title>
  </head>
  <body>
    <h1>ブログ一覧(ページ {page})</h1>

    <ul>
      {posts.map(post => (
        <li>
          <a href={`/blog/${post.slug}`}>{post.title}</a>
        </li>
      ))}
    </ul>

    <div>
      {prevPage && <a href={prevPage}>« 前のページ</a>}
      {nextPage && <a href={nextPage}>次のページ »</a>}
    </div>
  </body>
</html>

/blog/ へのリダイレクト設定

通常、/blog/ には 1ページ目の内容 を表示させたいので、リダイレクトする src/pages/blog/index.astro を作成します。

---
// returnしないとリダイレクトしないで注意‼
return Astro.redirect('/blog/page/1');
---

これで /blog/ にアクセスすると、/blog/page/1 にリダイレクトされます。

実装結果

この設定を適用すると、ブログ記事一覧が 3件ずつページ分割される ようになります。

7つの記事が3ページに分かれて表示されるようになり、下部には簡単なページネーションが表示されました。

CSSで見た目を整えれば完成です。

まとめ

  • getStaticPaths を活用することで、ページネーションを簡単に実装 できる
  • /blog/page/[page].astro で動的なページ番号を取得し、記事リストを分割して表示

次のセクションでは、パンくずリストの実装例 を解説します。パンくずリストを追加することで、ユーザーが現在のページの位置を直感的に把握しやすくなります。

2-3. パンくずリストの実装例

パンくずリスト(Breadcrumbs)は、ユーザーが現在いるページの階層構造を示すナビゲーション です。例えば、ブログ記事ページで以下のように表示されます。

ホーム > ブログ > ルーティング完全ガイド

パンくずリストを設置すると、以下のメリットがあります。

  • ユーザーの利便性向上・・・現在のページが サイト内のどこに位置しているのか を明確にできる 1クリックで上位階層に戻れる
  • SEO対策・・・Google検索結果で 構造化データ を利用した表示が可能(リッチリザルト対応) 内部リンクが適切に設定され、検索エンジンがサイトの構造を理解しやすくなる

パンくずリストの基本実装

Astroでは、パンくずリストをコンポーネント化 することで、複数のページで再利用できます。

  1. パンくずリストのコンポーネント(src/components/Breadcrumb.astro)
---
const { paths } = Astro.props;
---
<nav aria-label="パンくずリスト">
  <ul>
    {paths.map((path, index) => (
      <li>
        {index < paths.length - 1 ? (
          <a href={path.href}>{path.label}</a>
        ) : (
          <span>{path.label}</span>
        )}
      </li>
    ))}
  </ul>
</nav>

<style>
	nav {
		background-color: rgba(240, 240, 240, 1);
		padding: 5px 8px;
	}

	ul {
		list-style: none;
		padding: 0;
		margin: 0;
		display: flex;
		gap: 5px;

		& > li:not(:last-child) {
			&::after {
				content: '>';
			}
		}
	}
</style>

このコンポーネントは、paths プロパティを受け取り、各ページのリンクをリスト表示します。

各ページでの使用例

  1. ブログ記事ページ(src/pages/blog/[slug].astro)
---
import blogData from "../../content/blog.json";
import Breadcrumb from "../../components/Breadcrumb.astro";

// ルートパラメータを取得
const { slug } = Astro.params;
const post = blogData.find((p) => p.slug === slug);

// パンくずリストのデータ
const breadcrumbs = [
  { label: "ホーム", href: "/" },
  { label: "ブログ", href: "/blog/" },
  { label: post.title, href: `/blog/${slug}` },
];
---
<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<title>{ post?.title }</title>
	</head>
	<body>
		<Breadcrumb paths={breadcrumbs} />
		<h1>{ post?.title }</h1>
		<p>この記事のスラッグは「{ slug }」です。</p>
	</body>
</html>

2.Aboutページ(src/pages/about.astro)

---
import Breadcrumb from '../components/Breadcrumb.astro';
const title = "私たちについて";

const breadcrumbs = [
	{ label: 'ホーム', href: '/' },
	{ label: '私たちについて', href: '/about' },
];
---

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>{title}</title>
</head>
<body>
	<Breadcrumb paths={breadcrumbs} />
	<h1>{title}</h1>
	<p>私たちの会社について紹介します。</p>
</body>
</html>

SEO対策のための構造化データ(JSON-LD)

Googleの検索結果に パンくずリストをリッチリザルトとして表示させるには、構造化データ(JSON-LD)を追加すると効果的です。

JSON-LDを追加するコード(src/pages/blog/[slug].astro に挿入)

---
import blogData from '../../content/blog.json';
import Breadcrumb from '../../components/Breadcrumb.astro';

export async function getStaticPaths() {
	return blogData.map((post) => ({
		params: { slug: post.slug },
	}));
}

const { slug } = Astro.params;
const post = blogData.find((post) => post.slug === slug);

const breadcrumbs = [
	{ label: 'ホーム', href: '/' },
	{ label: 'ブログ', href: '/blog' },
	{ label: post?.title, href: `/blog/${slug}` },
];

const breadcrumbSchema = {
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": breadcrumbs.map((item, index) => ({
    "@type": "ListItem",
    "position": index + 1,
    "name": item.label,
    "item": item.href
  }))
};
---

<html lang="ja">
	<head>
		<meta charset="UTF-8" />
		<title>{ post?.title }</title>
    <script type="application/ld+json" set:html={JSON.stringify(breadcrumbSchema)}></script>
	</head>
	<body>
		<Breadcrumb paths={breadcrumbs} />
		<h1>{ post?.title }</h1>
		<p>この記事のスラッグは「{ slug }」です。</p>
	</body>
</html>

補足:パンくずリストを構造化するとどうなるの?

構造化データをWebページに設置すると、検索結果にパンくずリストが表示されるようになります。構造化データを設置しないときは、検索結果にはURLが表示されます。構造化データにすることによってキーワードへのアプローチが正確になりSEOに有効になります。

構造化データパンくずリストのGoogle検索結果表示。アルファベットではなくちゃんと日本語になっている

実装結果

この設定を適用すると、以下のようにパンくずリストが表示されます。

また、Google検索結果のリッチリザルトとして、パンくずリストが表示される可能性が高まります。

構造化データ化されたパンくずリストのソース

まとめ

  • パンくずリストは、ユーザーの利便性向上&SEO対策に有効
  • Breadcrumb.astro をコンポーネント化して、簡単に再利用が可能になる
  • 構造化データ(JSON-LD)を追加すると、検索結果のリッチリザルトにも対応できる

次のセクションでは、3-4.パラメーターの利用方法 を解説します。ルーティングで動的なパラメーターをどのように活用できるかを詳しく説明します。

2-4. パラメーターの利用方法

AstroはSSGが優先的に選択されるのでクエリパラメーター(?key=value)を利用するには注意が必要です。

SSGでクエリパラメーターの値を取得して出力するには大きく2種類の方法があります。

  • astroファイル内にscriptタグを書いてデータを取得後DOMを更新する
  • ReactやVueなどの他のフレームワークを利用して取得する

この2種類の方法を使ってクエリパラメータの値を取得していきます。

クエリパラメーターとは?

たとえば、以下のようなURLを想定します。

/search?keyword=astro

URLの「keyword」がkey。「astro」がvalueになります。

次のセクションからページにこのvalueの値を表示していきます。

astroファイル内にscriptタグを書いてデータを取得後、DOMを更新する方法

src/pages/search.astroファイルを以下のようにします。

<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>検索結果</title>
  </head>
  <body>
		<h1 id="search-result"></h1>
  </body>
</html>

<script>
	document.addEventListener("DOMContentLoaded", function() {
		const params = new URLSearchParams(window.location.search);
		const keyword = params.get("keyword") || "未指定";
		document.getElementById("search-result").textContent = `検索キーワード: ${keyword}`;
	});
</script>

このコードでは、/search?keyword=astro にアクセスすると、「astro」の検索結果ページが表示されます。

ReactやVueなどの他のフレームワークを利用して取得する

今回はReactを利用します。ハイドレーションでclient:loadのタイミングでReactでURLのパラメータを取得して出力するようにします。

Reactの部分はコンポーネントで読み込むようにします。

AstroでReactを利用する方法は別記事でも書いていますのでこちらを参考に導入してください。

コマンド一発で導入できるので簡単です。

Reactが導入されたことを前提として次の2ファイルを操作します。

  • src/pages/search.astro
  • src/components/SearchKeyword.jsx(新規作成)

各ファイルを次のようにします。

▼src/components/SearchKeyword.jsx

import { useEffect, useState } from "react";

export default function SearchKeyword() {
  const [keyword, setKeyword] = useState("検索ワード未指定");

  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    setKeyword(params.get("keyword") || "検索ワード未指定");
  }, []);

  return <h1>検索キーワード:{keyword}</h1>;
}

▼src/pages/search.astro

---
import SearchKeyword from "../components/SearchKeyword.jsx";
---

<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>検索結果</title>
  </head>
  <body>
		<SearchKeyword client:load />
  </body>
</html>

このコードでも①同様に/search?keyword=astro にアクセスすると、「astro」の検索結果ページが表示されます。

クエリパラメータから取得されたキーワードが表示されているのがわかる

まとめ

  • クエリパラメーターを利用する場合はSSGなのかSSRなのか意識することが重要
  • クライアントサイドで読み込む方法とハイドレーションを利用した2種類の方法が存在する
  • 検索やフィルタリングなどの動的な処理を行いたい場合はクエリパラメーター の使用を考える

次のセクションでは、3-5. APIルートの設定方法 を解説します。AstroでのAPIエンドポイントの作成方法と活用例 を紹介します。

2-5. APIルートの設定方法

AstroにおけるAPIルートとは?

Astroでは、src/pages/api/ フォルダ内にファイルを作成すると、そのファイルがAPIエンドポイントとして機能します。例えば、以下のようなファイル構成があるとします。

/src/pages/api/posts.json.ts

このファイルにコードを記述すれば、APIエンドポイント(/api/posts.json を作成できます。APIエンドポイントは、データの取得や外部サービスとの通信に便利 です。

基本的なAPIエンドポイントの作成

以下は、ブログ記事のリストをJSON形式で返すAPIの実装例です。

1. APIルートの作成(src/pages/api/posts.json.ts

import type { APIRoute } from "astro";

const blogPosts = [
  { id: 1, title: "Astroのルーティング", slug: "astro-routing" },
  { id: 2, title: "SEOの基本", slug: "seo-tips" },
];

export const GET: APIRoute = async () => {
  return new Response(JSON.stringify(blogPosts), {
    headers: { "Content-Type": "application/json" },
  });
};

2. エンドポイントの利用

このファイルを配置すると、/api/posts.json にアクセスした際、次のようなJSONデータが返されます。

[
  { "id": 1, "title": "Astroのルーティング", "slug": "astro-routing" },
  { "id": 2, "title": "SEOの基本", "slug": "seo-tips" }
]

このAPIは、ブログ一覧を取得する際に便利です。

動的パラメーターを使用したAPI

APIエンドポイントでも動的ルーティングを利用できます。例えば、特定のブログ記事を取得するAPIを作る場合、[slug].json.ts を作成します。

動的パラメータを使用したAPIの利用はSSRモードでの対応になります。SSGでは設定できません。

AstroをSSRモードにするにはastro.config.mjsdefineConfig関数内にoutput: 'server'を追記します。以前は'hybrid'という良いとこどりの設定ができましたがAstroのバージョン5からは'static''server'のいずれかになるので注意が必要です。

3. 動的APIエンドポイントの作成

src/pages/api/posts/[slug].json.tsファイルを以下のようにします。※SSRモードになっていることが前提です。

import type { APIRoute } from "astro";

const blogPosts = [
  { id: 1, title: "Astroのルーティング", slug: "astro-routing", content: "Astroのルーティングについて..." },
  { id: 2, title: "SEOの基本", slug: "seo-tips", content: "SEOの基本を解説..." },
];

export const GET: APIRoute = async ({ params }) => {
  const post = blogPosts.find((p) => p.slug === params.slug);

  if (!post) {
    return new Response(JSON.stringify({ error: "記事が見つかりません" }), {
      status: 404,
      headers: { "Content-Type": "application/json" },
    });
  }

  return new Response(JSON.stringify(post), {
    headers: { "Content-Type": "application/json" },
  });
};

このAPIを作成すると、以下のようなURLで個別のブログ記事データが取得できます。

  • /api/posts/astro-routing.json
  • /api/posts/seo-tips.json

例えば、/api/posts/astro-routing.json にアクセスすると、次のJSONが返されます。

{
  "id": 1,
  "title": "Astroのルーティング",
  "slug": "astro-routing",
  "content": "Astroのルーティングについて..."
}

APIルートをフロントエンドで利用する

AstroのAPIルートをフロントエンドで利用するには、fetch を使います。例えば、ブログの一覧を取得する場合、以下のように記述します。

4. フロントエンドでAPIを利用する(src/pages/posts.astro

astroファイル内でfetchを利用し先ほど作成したapi 用のURLへリクエストを投げ返ってきたデータをもとにリストを出力します。

import.meta.env.SITEを利用するためにはastro.config.mjsのdefineConfig関数にsiteの設定が必要です。今回はsite: 'http://localhost:4321'と設定しています。

---
const response = await fetch( import.meta.env.SITE + '/api/posts.json');
const posts = await response.json();
---
<html>
  <head>
    <title>ブログ一覧</title>
		<meta charset="utf-8">
  </head>
  <body>
    <h1>ブログ一覧</h1>
    <ul>
      {posts.map((post) => (
        <li>
          <a href={`/blog/${post.slug}`}>{post.title}</a>
        </li>
      ))}
    </ul>
  </body>
</html>

このコードで以下のようなページ表示になります。

APIルートの応用例

外部APIと連携

  • AstroのAPIルートを使って、外部のデータ(CMS、データベース、サードパーティAPI)を取得し、サイトに表示

フォームの処理(POSTリクエスト)

  • AstroのAPIルートで POST メソッドを受け付け、データを処理
  • 例: src/pages/api/contact.ts を作成し、フォーム送信を処理
export const POST: APIRoute = async ({ request }) => {
  const data = await request.json();
  console.log("フォームデータ:", data);

  return new Response(JSON.stringify({ message: "送信完了" }), {
    headers: { "Content-Type": "application/json" },
  });
};

このエンドポイントに対して、以下のようにデータを送信できます。

fetch("/api/contact", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "太郎", email: "taro@example.com" })
});

まとめ

  • AstroのAPIルート を使うと、簡単にJSONデータを提供できる
  • pages/apiフォルダ内に処理を書いたファイルを作成する
  • 動的パラメーターを利用する場合はSSRモードのみ対応

3. 最後に

本記事では、Astroのルーティング について解説しました。Astroはシンプルな構成ながら柔軟なルーティング機能を備えており、静的サイトから動的アプリケーションまで幅広く対応できます。

Astroのルーティングの基本

  • Astroはファイルベースのルーティングを採用しており、フォルダ構造がそのままURL構造に反映される。
  • 静的ルーティング では、通常の .astro ファイルを src/pages/ に配置するだけでページが作成可能。
  • 動的ルーティング では、[slug].astro などのパラメーターを含むルートを定義できる。

ルーティング設定の実例

  • getStaticPaths を活用することで、ビルド時に動的ページを静的生成 できる。
  • ページネーションパンくずリスト の実装方法を紹介し、SEOやユーザビリティを考慮した構成が可能。
  • パラメーターの利用 により、動的なURL構造を実現し、ユーザーごとに異なるコンテンツを提供可能。
  • APIルートの設定 によって、JSONデータの提供やフォーム送信の処理が行える。

Astroのルーティングを活用するメリット

パフォーマンスの向上

  • 静的ページの事前生成により、高速なページロード が可能。
  • getStaticPaths を使えば、ビルド時に必要なページを生成し、クライアントでのレンダリングを最小限に抑えられる。

SEOに強い

  • 静的HTMLを生成できるため、検索エンジンに最適化されたページを提供できる。
  • 適切なルーティング設計により、ページのインデックス登録内部リンクの最適化 も容易。

拡張性の高さ

  • Astroのルーティングは、単純な静的サイトだけでなく、動的なデータ取得API連携 にも対応可能。
  • さまざまなフレームワーク(React, Vue, Svelte)と組み合わせて、インタラクティブなUIを構築できる。

まとめ:Astroのルーティングを理解し、最適なサイト構築へ

Astroのルーティング機能を活用することで、静的サイトの高速性と動的サイトの柔軟性を両立 したWebサイトを構築できます。

  • シンプルな静的サイト から 大規模な動的アプリケーション まで、幅広く対応可能。
  • SEO最適化やパフォーマンス向上 にも貢献する、実践的なアプローチが可能。
  • API連携や動的ページ生成 を組み合わせれば、より高度なWebサイト開発が実現できる。

今後、Astroのルーティングをさらに活用し最適な構成を模索していきましょう!