コンテンツにスキップ

タグページを生成する

ここで学ぶことは…

  • 複数のページを生成するためのページを作成する
  • どのページルートをビルドするかを指定し、各ページに個別のプロパティを渡す

動的なページルーティング

getStaticPaths()関数をエクスポートする.astroファイルを使用して、ページの集まりを動的に作成できます。

動的にページを作成する

  1. src/pages/tags/[tag].astroに新しいファイルを作成します。(まず新しいフォルダを作成する必要があります。)ファイル名([tag].astro)に角括弧が含まれていることに注意してください。以下のコードをファイルに貼り付けます。

    src/pages/tags/[tag].astro
    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    export async function getStaticPaths() {
    return [
    { params: { tag: "astro" } },
    { params: { tag: "成功" } },
    { params: { tag: "コミュニティ" } },
    { params: { tag: "ブログ" } },
    { params: { tag: "後退" } },
    { params: { tag: "公開学習" } },
    ];
    }
    const { tag } = Astro.params;
    ---
    <BaseLayout pageTitle={tag}>
    <p>{tag}のタグが付いた記事</p>
    </BaseLayout>

    getStaticPaths関数はページのルートの配列を返します。各ルートに対応するページは、このファイルで定義されたものと同じテンプレートを使用します。

  2. ブログ記事をカスタマイズしている場合は、個々のタグの値(たとえば「astro」、「成功」、「コミュニティ」など)を、記事で使用されているタグに置き換えます。

  3. すべてのブログ記事が少なくとも1つのタグを含んでいることを確認します。tags: ["ブログ"]のように、配列として書く必要があります。

  4. ブラウザのプレビューでhttp://localhost:4321/tags/astroにアクセスすると、[tag].astroから動的に生成されたページが表示されるはずです。/tags/成功/tags/コミュニティ/tags/公開学習など、その他の各カスタムタグについてページが作成されていることも確認してください。これらの新しいページを表示するには、まず開発サーバーを終了して再起動する必要があるかもしれません。

動的ルートでpropsを使用する

  1. 以下のpropsをgetStaticPaths()関数に追加して、すべてのブログ記事のデータを各ページルートで利用できるようにします。

    配列内の各ルートに新しいpropsを定義し、そのpropsを関数の外側のコンポーネントテンプレートで利用できるようにしてください。

    src/pages/tags/[tag].astro
    ---
    import BaseLayout from '../../layouts/BaseLayout.astro';
    export async function getStaticPaths() {
    const allPosts = await Astro.glob('../posts/*.md');
    return [
    {params: {tag: "astro"}, props: {posts: allPosts}},
    {params: {tag: "成功"}, props: {posts: allPosts}},
    {params: {tag: "コミュニティ"}, props: {posts: allPosts}},
    {params: {tag: "ブログ"}, props: {posts: allPosts}},
    {params: {tag: "後退"}, props: {posts: allPosts}},
    {params: {tag: "公開学習"}, props: {posts: allPosts}}
    ]
    }
    const { tag } = Astro.params;
    const { posts } = Astro.props;
    ---
  2. 記事のリストを、ページのタグを含む記事のみへとフィルタリングします。

    /src/pages/tags/[tag].astro
    ---
    const { tag } = Astro.params;
    const { posts } = Astro.props;
    const filteredPosts = posts.filter((post) => post.frontmatter.tags?.includes(tag));
    ---
  3. 以上により、HTMLテンプレートを更新して、ページのタグを含むブログ記事のリストを表示できるようになりました。以下のコードを[tag].astroに追加します。

    src/pages/tags/[tag].astro
    <BaseLayout pageTitle={tag}>
    <p>{tag}のタグが付いた記事</p>
    <ul>
    {filteredPosts.map((post) => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}
    </ul>
    </BaseLayout>
  4. <BlogPost />コンポーネントを使用するよう、さらにリファクタリングしてみましょう!([tag].astroの先頭でこのコンポーネントをインポートするのを忘れないでください。)

    src/pages/tags/[tag].astro
    <BaseLayout pageTitle={tag}>
    <p>{tag}のタグが付いた記事</p>
    <ul>
    {filteredPosts.map((post) => <li><a href={post.url}>{post.frontmatter.title}</a></li>)}
    {filteredPosts.map((post) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
    </ul>
    </BaseLayout>
  5. ブラウザのプレビューで各タグページを確認すると、特定のタグを含むブログ記事のリストが表示されるはずです。

パターンを分析する

以下の各項目について、コードがgetStaticPath()関数の内側に書かれるか、それとも外側に書かれるか選択してください。

  1. .mdファイルに関する情報を受け取り、各ページルートに渡すためのAstro.glob()の呼び出し。

  2. getStaticPaths()によって生成(返却、return)されるルートのリスト。

  3. HTMLテンプレートで使用する、propsparamsを受け取るための値。

高度なJavaScript: 既存のタグからページを生成する

これで、各タグページは[tag].astroにおいて静的に定義されました。ブログ記事に新しいタグを追加する場合は、このページを再度開きページルートを更新する必要があります。

以下では、このページのコードを、ブログページで使用されている各タグを取得してページを自動的に生成するコードへと置き換える例を示します。

1. すべてのブログ記事にタグが含まれていることを確認する

既存のMarkdownページをそれぞれ再度開き、すべての記事のフロントマターにtags配列が含まれていることを確認します。1つのタグしかない場合でも、tags: ["blogging"]のように配列として書く必要があります。

2. すべての既存タグの配列を作成する

以下のコードを追加して、ブログ記事で使用されているすべてのタグのリストを取得します。

src/pages/tags/[tag].astro
---
import BaseLayout from '../../layouts/BaseLayout.astro';
export async function getStaticPaths() {
const allPosts = await Astro.glob('../posts/*.md');
const uniqueTags = [...new Set(allPosts.map((post) => post.frontmatter.tags).flat())];
このコードに関する詳細を表示

こうしたコードを今まで自分で書いたことがなくても大丈夫です!

ここではまず1つずつMarkdownの投稿を処理し、タグの配列を1つの大きな配列へと結合しています。次に、(繰り返される値を無視するために)見つかったすべてのタグから新しいSetを作成します。最後に、その集合(Set)を配列に変換します(この段階で重複はなくなっています)。これで、ページにタグのリストを表示するために使用するための配列ができました。

以上により、"astro""成功""コミュニティ""ブログ""後退""公開学習"という要素をもつ配列uniqueTagsができました。

3. getStaticPaths関数のreturn値を置き換える

src/pages/tags/[tag].astro
return [
{params: {tag: "astro"}, props: {posts: allPosts}},
{params: {tag: "成功"}, props: {posts: allPosts}},
{params: {tag: "コミュニティ"}, props: {posts: allPosts}},
{params: {tag: "ブログ"}, props: {posts: allPosts}},
{params: {tag: "後退"}, props: {posts: allPosts}},
{params: {tag: "公開学習"}, props: {posts: allPosts}}
]
return uniqueTags.map((tag) => {
const filteredPosts = allPosts.filter((post) => post.frontmatter.tags.includes(tag));
return {
params: { tag },
props: { posts: filteredPosts },
};
});

getStaticPaths関数は、params(各ページルートの名前)を含むオブジェクトのリストを常に返す必要があります。また、任意でprops(各ページに渡したいデータ)を含めることもできます。先ほどまでは、ブログで使用されている各タグ名を自分で指定し、各ページにすべての記事データをpropsとして渡していました。

ここでは、uniqueTags配列を使用して各パラメータを定義し、このオブジェクトのリストを自動的に生成しています。

さらに、ブログ記事のリストは、各ページにpropsとして渡される前にフィルタリングされるようになりました。記事のフィルタリングをおこなっていた以前のコードを削除し、filteredPostsではなくpostsを使用するようにHTMLテンプレートを更新してください。

src/pages/tags/[tag].astro
const { tag } = Astro.params;
const { posts } = Astro.props;
const filteredPosts = posts.filter((post) => post.frontmatter.tags.includes(tag));
---
<!-- -->
<ul>
{filteredPosts.map((post) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
{posts.map((post) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
</ul>

最終的なコードのサンプル

ここまでの自分の作業内容を確認したい場合や、[tag].astroにコピーするための完全で正しいコードが欲しい場合のために、現段階でのAstroコンポーネントを以下に示します。

src/pages/tags/[tag].astro
---
import BaseLayout from '../../layouts/BaseLayout.astro';
import BlogPost from '../../components/BlogPost.astro';
export async function getStaticPaths() {
const allPosts = await Astro.glob('../posts/*.md');
const uniqueTags = [...new Set(allPosts.map((post) => post.frontmatter.tags).flat())];
return uniqueTags.map((tag) => {
const filteredPosts = allPosts.filter((post) => post.frontmatter.tags.includes(tag));
return {
params: { tag },
props: { posts: filteredPosts },
};
});
}
const { tag } = Astro.params;
const { posts } = Astro.props;
---
<BaseLayout pageTitle={tag}>
<p>{tag}のタグが付いた記事</p>
<ul>
{posts.map((post) => <BlogPost url={post.url} title={post.frontmatter.title}/>)}
</ul>
</BaseLayout>

これで、ブラウザのプレビューで任意のタグページを表示できるようになりました。

http://localhost:4321/tags/コミュニティに移動すると、コミュニティというタグが付いたブログ記事のリストが表示されるはずです。同様に、http://localhost:4321/tags/公開学習では、公開学習というタグが付いたブログ記事のリストが表示されます。

次のセクションでは、これらのページへのナビゲーションリンクを作成します。

確認テスト

説明文に合う用語を選択してください。

  1. ページルートの配列を返す関数。

  2. Astroで1つのファイルから複数のページルートを作成するためのプロセス。

  3. 動的に生成されるページルートの名前を定義する値。

チェックリスト

参考