AstroでMarkdown記事の詳細ページをgetStaticPathsで生成する
AstroでMarkdown記事の詳細ページを作る場合、getStaticPaths() を使ってURLを生成します。
src/content/posts/foo.md を /posts/foo/ として出したい、というケースです。
Astro公式の動的ルーティングにも、getStaticPaths() を使う流れが載っています。
https://docs.astro.build/en/guides/routing/#dynamic-routes
ファイル構成
src/
├── content/
│ └── posts/
│ └── first-post.md
└── pages/
└── posts/
└── [...slug].astro
[...slug].astro で、Markdownファイルごとのページを生成します。
getStaticPathsを書く
---
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('posts', ({ data }) => !data.draft);
return posts.map((post) => ({
params: { slug: post.id.replace(/\.mdx?$/, '') },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await render(post);
---
<article>
<h1>{post.data.title}</h1>
<Content />
</article>
params.slug がURLになります。
first-post.md なら /posts/first-post/ になります。
renderで本文を出す
Content Collectionsの記事本文は render(post) でコンポーネントとして取り出します。
const { Content } = await render(post);
その後、Astroコンポーネント内で <Content /> として表示します。
slug生成は共通化する
一覧ページと詳細ページでURL生成ルールがずれると困ります。
ヘルパーを作っておくと扱いやすいです。
import type { CollectionEntry } from 'astro:content';
export function getPostSlug(post: CollectionEntry<'posts'>) {
return post.id.replace(/\.mdx?$/, '');
}
export function getPostUrl(post: CollectionEntry<'posts'>) {
return `/posts/${getPostSlug(post)}/`;
}
まとめ
AstroでMarkdown記事詳細を作るなら、流れはこの形です。
src/pages/posts/[...slug].astroを作るgetCollection()で記事を取得するgetStaticPaths()でURLを返すrender(post)で本文を描画する- slug生成は共通化する
記事URLは後から変えると面倒なので、最初にルールを固定しておくのが重要です。


