nextjsと比べてastroで動的ルーティングをするのは少しわかりにくかったので、備忘録としてまとめます
公式ドキュメント
https://docs.astro.build/ja/guides/routing/#dynamic-routes
動的ルーティング
基礎
ルーティング方法はドキュメントの通り。 それほど難しくはないと思います。
動的ルーティングの指定は、nextjsのように []で囲って行う。
Astro.paramsからURLパラメータを取得できる。
const { dog } = Astro.params
ここからが追加の設定で、
公式ドキュメント曰く以下のような getStaticPaths()の設定が必須。
export function getStaticPaths() {
return [
{ params: { dog: "clifford" }},
{ params: { dog: "rover" }},
{ params: { dog: "spot" }},
];
}
これで、
- /dogs/clifford
- /dogs/rover
- /dogs/spot
のページが生成される。
単純にURLのパラメータを用いるだけならこのようにして、
<html>
<body>
param = { dog }
</body>
</html>
として、表示すればいい。
md等の別ファイルを表示したい
ブログなどの場合、大幅に別の内容を表示したいです。 例えば、
/dogs/cliffordの場合、clifford.mdを表示させたい。/dogs/roverの場合、rover.mdを表示させたい。
というような場合、少し追加の実装が必要です。
docs:https://docs.astro.build/en/guides/content-collections/#querying-collections
astroではコンテンツコレクションというものがあります。 ブログの記事等をここに登録して、表示させます。
load
詳細はドキュメントをご覧ください。 https://docs.astro.build/en/guides/content-collections/#defining-collections
src/content.config.tsを作成し、
次のように記述します。
import { glob } from "astro/loaders";
import { defineCollection, z } from "astro:content";
const posts = defineCollection({
loader: glob({
pattern: "**/*.md",
base: "./src/content/",
}),
schema: //schema
});
export const collections = { dogs };
これで dogsというコンテンツコレクションが作成されます。
get
https://docs.astro.build/en/guides/content-collections/#querying-collections
コンテンツコレクションから内容を取得します。
const entry =await getEntry("dogs",dog);
文字列でコンテンツコレクションを設定するのはなんか気に入りませんが、こうするみたいです。 dogsコレクションの中の、dogにマッチするコンテンツを取得できます。
render
https://docs.astro.build/en/reference/modules/astro-content/#render
取得したコンテンツをレンダリング用にコンパイルします。
const {Content, headings } = await render(entry);
<html>
<Content/>
</html>
とすることでようやく動的にページ内容を表示できます。
補足
マッチング方法
getEntry("dogs",dog);
loader: glob(...) を使用している場合、ファイルパスが自動的に id として割り当てられる。
つまり、dogsコレクションのid(filepath)がdogであるものを取得している。
defineCollectionのschema
---
title: "title"
launch_date: 2025-12-21
status: "Active"
tags: ["tag"]
destination: "Web Development"
---
blog
astroのmdでは頭にこのように記述することができる。 この場合、schemaは
schema: z.object({
title: z.string(),
launch_date: z.date(),
status: z.enum(['Active', 'Inactive', 'Decommissioned']),
tags: z.string().array(),
destination: z.string(),
}),
とするのがいいかもしれない。 こうすることで、
entry.data.title
のように使うことができる。