【Astro】ブログ記事を動的にルーティングする

目次

執筆時の作業環境は以下のとおりです。

  • MacOS: Sonoma 14.2.1
  • Node.js: v21.6.1
  • npm: v10.2.4
  • Astro: v4.4.0

はじめに

Astroでは、コンテンツコレクションを使ってブログの記事などのコンテンツを管理することができます。コンテンツコレクションについての詳細はこちらをご覧ください。

コンテンツコレクションはpagesディレクトリ内にあるわけではないので、Webページとして表示するためにルーティングをする必要があります。AstroではgetStaticPath()を使ってコンテンツコレクションを動的にルーティングできます。

ルーティングのためのファイルを作成する

まずはページをどの改装に作成するかを決めるため、ルーティング用のファイルを作成します。今回は/blog/post-1のように作成したいので、src/pages/blogディレクトリ内に[slug].astroというファイルを作成します。

ページ内で[slug]の部分にパラメータを受け取ってルーティングをします。

ルーティングを実装する

ルーティングを実装するためのコードの全体像はこちらです。

---
// ①
import { getCollection } from 'astro:content'

// ②
export async function getStaticPaths() {
  const blogEntries = await getCollection('blog')
  return blogEntries.map((entry) => ({
    params: { slug: entry.slug },
    props: { entry },
  }))
}

// ③
const { entry } = Astro.props
const { Content } = await entry.render()
---

<Content />

getCollectionをインポートする

getCollectionはコンテンツコレクションからデータを取得するためのAPIです。

---
// ①
import { getCollection } from 'astro:content'
---

getStaticPathsを使ってパラメータを設定する

getStaticPathsでは、返り値にparamspropsのプロパティをもつオブジェクトを配列で渡すことで、paramsの値をURLスラッグに変換してページを作成します。

このコードでは、getCollectionで取得したデータをmapで展開して、各データのslugプロパティの値をparamsに格納しています。

また、propsに記事データを格納することでページ内で使用できるようにします。

---
// ①
import { getCollection } from 'astro:content'

// ②
export async function getStaticPaths() {
  const blogEntries = await getCollection('blog')
  return blogEntries.map((entry) => ({
    params: { slug: entry.slug },
    props: { entry },
  }))
}
---

③ 記事をレンダリングする

記事をHTMLにレンダリングするために、render()メソッドからContentを定義します。

このContentをテンプレートエリアで<Content />と書くことでparamsで設定したURLのページに記事が表示されます。

---
// ①
import { getCollection } from 'astro:content'

// ②
export async function getStaticPaths() {
  const blogEntries = await getCollection('blog')
  return blogEntries.map((entry) => ({
    params: { slug: entry.slug },
    props: { entry },
  }))
}

// ③
const { entry } = Astro.props
const { Content } = await entry.render()
---

<Content />

Contentでレンダリングされるのは、マークダウンファイルに書かれた部分だけです。

マークダウンのフロントマッターにlayoutというプロパティでレイアウトコンポーネントを指定して<head>タグなどHTMLに必要な要素を組み込みましょう。

おわり

今回は単階層でのルーティングでしたが、複数の階層にまたがったルーティングをする場合にはレストパラメータを設定できるなど、柔軟な実装が可能です。とても便利ですね。

以上

参考

ルーティング

Astroのルーティングの紹介