[Astro] 静的サイトジェネレーター [ルーティング]

ルーティング

静的ルーティング

src/pages ディレクトリにある、Astro コンポーネント (.astro) と Markdown ファイル (.md) は自動的にウェブサイトのページとなります。

動的ルーティング

1つの Astro ページコンポーネントは、ファイル名に動的ルーティングパラメータを指定して、指定した条件に合致する複数のルーティングを生成することもできます。

名前付きパラメータ

以下のように getStaticPaths() 関数を使用する値を指定することで、名前付きパラメータを持つルーティングを生成できます。
src/pages/dogs/[dog].astro

---
export function getStaticPaths() {
    return [
        // 生成対象: /dogs/clifford
        { params: { dog: 'clifford' } },
        // 生成対象: /dogs/rover
        { params: { dog: 'rover' } },
        // 生成対象: /dogs/spot
        { params: { dog: 'spot' } },
    ];
}
---

動的にルーティングを生成する Astro コンポーネントは、各ルーティングに対して Astro.params オブジェクトを利用できます。
src/pages/posts/[id].astro

---
const { id } = Astro.params;
---
<p>post: { id }</p>

// ルーティング '/post/abc' に渡される Astro.params オブジェクト
{ "id": "abc" }

複数の動的ルーティングセグメントを組み合わせて、同じように動作させることができます。
src/pages/post/[id]/[comment].astro

---
const { id, comment } = Astro.params;
---

// ルーティング '/post/abc/a-comment' に渡される Astro.params オブジェクト
{ "id": "abc", "comment": "a-comment" }

レストパラメーター

URLルーティングに柔軟性が必要な場合は、.Astro ファイル名にレストパラメーターを使用します。これは、ブラケット内に3つのドット (…) を追加して、深さに関係なく、ファイルパスをすべて受け取れます。

ルーティングの優先順位

・パスパラメーターを持たない静的ルーティングは、他のすべてのルーティングよりも優先
・名前付きパラメーターを使用する動的ルーティングは、レストパラメーターよりも優先
・レストパラメーターはもっとも低い優先度
・同順位はアルファベット順に解決される

ページ分割

Astro は、複数のページに分割する必要がある大規模なデータコレクションのために、ビルトインのページ分割をサポートしています。Astro は、前ページ/次ページの URL、総ページ数など、一般的なページネーションプロパティを生成します。
/src/pages/astronauts/[page].astro

---
export async function getStaticPaths({ paginate }) {
  const astronautPages = [{
    astronaut: 'ニール・アームストロング',
  }, {
    astronaut: 'バズ・オルドリン',
  }, {
    astronaut: 'サリー・ライド',
  }, {
    astronaut: 'ジョン・グレン',
  }];
  // 宇宙飛行士の配列から、1ページに2人づつ入るようにページを生成する
  return paginate(astronautPages, { pageSize: 2 });
}
// ページ分割されたデータは、すべて "page" プロパティとして渡される
const { page } = Astro.props;
---

<!-- 現在のページ番号を表示します。Astro.params.page も使用可能です -->
<h1>{ page.currentPage }page</h1>
<ul>
  <!-- 宇宙飛行士情報の配列を列挙する -->
  { page.data.map(({ astronaut }) => <li>{ astronaut }</li>) }
</ul>

page プロパティ

paginate() 関数を使用すると、各ページのデータは page プロパティで渡されます。page プロパティは多くの便利なプロパティを持っていますが、ここではそのハイライトを紹介します。
/src/pages/astronauts/[page].astro

---
// 前の例と同じように、{ astronaut } オブジェクトのリストをページ分割します
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
<h1>{ page.currentPage }page</h1>
<ul>
  { page.data.map(({ astronaut }) => <li>{ astronaut }</li>) }
</ul>
{ page.url.prev ? <a href={ page.url.prev }>Previous</a> : null }
{ page.url.next ? <a href={ page.url.next }>Next</a> : null }

ネストされたページ分割

ページ分割のより高度なユースケースはネストされたページ分割です。これは、ページ分割を他の動的ルーティングパラメーターと組み合わせた場合です。ネストされたページ分割を使用すると、ページ分割されたコレクションを何らかのプロパティやタグでグループ化できます。
/src/pages/[tag]/[page].astro

---
export function getStaticPaths({paginate}) {
  const allTags = ['red', 'blue', 'green'];
  const allPosts = await Astro.glob('../../posts/*.md');
  // すべてのタグに対して、paginate() の結果を返す
  // 必ず、'{ params: { tag } }' を 'paginate()' に渡してください
  // そうすれば、Astroは結果がどのタググループに対するものか分かります
  return allTags.map((tag) => {
    const filteredPosts = allPosts.filter((post) => post.frontmatter.tag === tag);
    return paginate(filteredPosts, {
      params: { tag },
      pageSize: 10
    });
  });
}
const { page } = Astro.props;
const params = Astro.params;