Astro フレームワークのタグページを動的に生成する
2024-07-09
はじめに
Astro フレームワークの投稿のタグを所得し、タグを利用した投稿のページ一覧を生成します。
動的ページな tag ページを作成する
tag ごとのページを動的に作成します。
tag ページには、tag が付いている投稿一覧を表示します。
src/pages/tags/[tag].astro
に新規ファイルを作成します。ファイル名に []
が含まれていることに注意してください。
---
// src/pages/tags/[tag].astro
import Layout from "~/layouts/Layout.astro";
import Header from "~/components/Header.astro";
import Footer from "~/components/Footer.astro";
import { getCollection } from "astro:content";
export async function getStaticPaths() {
const posts = await getCollection("posts");
// Get all unique tags
const uniqueTags = [...new Set(posts.map((post) => post.data.tags).flat())];
return uniqueTags.map((tag) => {
// Filter posts by tag
const filteredPosts = posts.filter((post) => post.data.tags.includes(tag));
return {
params: { tag },
props: { posts: filteredPosts },
};
});
}
const { tag } = Astro.params;
const { posts } = Astro.props;
---
<Layout title=`Tag: ${tag}`>
<Header />
<main>
<section>
<h1 class="large-tag">{tag}</h1>
<p>タグに関連する投稿一覧です。</p>
</section>
<section>
<h2>Posts</h2>
<ul>
{
posts.map((post) => (
<li>
<a href={`/posts/${post.slug}`}>{post.data.title}</a>
</li>
))
}
</ul>
</section>
</main>
<Footer />
</Layout>
getStaticPaths()
で返却する params
へ動的に生成するページを配列で設定します。
ファイル名に動的パラメータを使用する場合、そのコンポーネントは getStaticPaths()
関数をエクスポートする必要があります。Astro は、 SSG のため、ビルド時に生成するページを指定する必要があるためのようです。
生成されたそれぞれの tag ページで利用する tag を利用している投稿を getStaticPaths()
で返却する props
へ設定します。
getCollection("posts")
で投稿を全て取得し、[...new Set(posts.map((post) => post.data.tags).flat())]
で投稿に含まれる tag の重複を削除しています。
タグ一覧ページを作成する
tag 一覧を作成します。 tag には、それぞれの tag ページへのリンクをします。
src/pages/tags/index.astro
を作成します。
---
// src/pages/tags/index.astro
import Layout from "~/layouts/Layout.astro";
import Header from "~/components/Header.astro";
import Footer from "~/components/Footer.astro";
import { getCollection } from "astro:content";
const posts = await getCollection("posts");
const tags = [...new Set(posts.map((post) => post.data.tags).flat())];
const title = "Tags";
---
<Layout title={title}>
<Header />
<main>
<section>
<h1>{title}</h1>
<p>タグ一覧です。</p>
</section>
<section>
<div class="flex flex-wrap mt-4">
{
tags.map((tag) => (
<span class="tag mr-2 my-1">
<a href={`/tags/${tag}`}>{tag}</a>
</span>
))
}
</div>
</section>
</main>
<Footer />
</Layout>
タグのスタイルを設定する
base.css
へ追記します。
.large-tag {
@apply bg-blue-500 text-white rounded-3xl px-6 py-2 text-2xl font-bold shadow-lg inline-block;
}
.tag {
@apply bg-blue-500 text-white rounded-lg px-3 py-1 text-sm font-semibold shadow-md inline-block;
}