Gatsby にキーワードページを導入する

投稿した記事にタグ付けするような機能は是非とも欲しいと思っていた。こちらもページネーションの記事同様、実装がさほど難しくなさそうだったのでプラグインではなく自前で実装した。

用意するもの

  • キーワード一覧ページ
  • キーワードに紐づく記事一覧ページ
    • レイアウト
    • URL

基本的にやることや用意するものはページネーションの記事と同じ。内部的に発行する GraphQL が多少違うだけ。

設計

Markdown内のキーワードの指定の仕方
1---
2title: タイトル
3date: 2021-03-26
4keywords:
5 - keyword_1
6 - keyword_2
7---
8
9## ヘッダ
10
11ここから記事本文

各記事のメタデータ記載部分に keywords という項目を作ることで記事にキーワードを付与する事ができるようにする。

キーワード一覧ページを作る

キーワード一覧ページは表示するコンテンツによって URL が変わったりしないためページコンポーネントとして作成した。

pages/keywords.js
1import React from "react"
2import { Link, graphql } from "gatsby"
3
4import GlobalLayout from "../layouts/global-layout"
5import SEO from "../components/seo"
6
7
8const Keywords = ({data}) => {
9 return (
10 <GlobalLayout>
11 <SEO title="Keyword List" />
12 <h3 className="page-label">Keyword list</h3>
13 <ul className="keyword-list">
14 {data.allMdx.group.map(({fieldValue, totalCount}, idx) => {
15 return (
16 <li key={idx}>
17 <Link to={`/keyword/${fieldValue}/`}>
18 {fieldValue}: {totalCount}
19 </Link>
20 </li>
21 )
22 })}
23 </ul>
24 </GlobalLayout>
25 )
26}
27
28export const query = graphql`
29 {
30 allMdx {
31 group(field: frontmatter___keywords) {
32 fieldValue
33 totalCount
34 }
35 }
36 }
37`
38
39
40export default Keywords

キーワードに紐づく記事一覧ページ

キーワード一覧ページが出来たら、今度はそのページから遷移する先の「選択されたキーワードに紐づく記事一覧ページ」が必要となる。

レイアウト

こちらは選択されたキーワードによって URL が変わるため gatsby-node.js で URL を作らないといけない。その際にレイアウトファイルを結びつける必要があるため先にレイアウトファイルを作る。

PostExcerpt コンポーネントは記事の見出し用コンポーネントで、トップページやページネーション内でも使っているもの。

layouts/keyword-page-layout.js
1import React from "react"
2import {graphql} from "gatsby"
3
4import GlobalLayout from "./global-layout"
5import SEO from "../components/seo"
6import PostExcerpt from "../components/post-excerpt"
7
8const KeywordPageLayout = ({data, pageContext}) => {
9 const pageTitle = `Keyword: "${pageContext.keyword}"`
10 return (
11 <GlobalLayout>
12 <SEO title={pageTitle} />
13 <h3 className="page-label">{pageTitle}</h3>
14 {data.allMdx.edges.map(({node}, idx) => {
15 return (
16 <PostExcerpt
17 key={idx}
18 createdDate={node.frontmatter.date}
19 name={node.slug}
20 title={node.frontmatter.title}
21 excerpt={node.excerpt}
22 />
23 )
24 })}
25 </GlobalLayout>
26 )
27}
28
29export const query = graphql`
30query KeywordPageLayoutQuery($keyword: String) {
31 allMdx(
32 filter: {frontmatter: {keywords: {eq: $keyword}}}
33 sort: {fields: frontmatter___date, order: DESC}
34 ) {
35 edges {
36 node {
37 frontmatter {
38 title
39 date
40 }
41 slug
42 excerpt
43 }
44 }
45 }
46}
47`
48
49export default KeywordPageLayout

URL 作成

つづいて URL 作成。一部抜粋したものだが下記のような感じ。これにより /keyword/<キーワード>/ という URL に対し、上で作った layouts/keyword-page-layout.js が対応してくれるようになる。

gatsby-node.js
1exports.createPages = async ({ graphql, actions }) => {
2 const { createPage } = actions
3 await createKeywordPages(graphql, createPage)
4}
5
6async function createKeywordPages(graphql, createPage) {
7 const result = await graphql(`
8 {
9 allMdx {
10 distinct(field: frontmatter___keywords)
11 }
12 }
13 `)
14 result.data.allMdx.distinct.forEach((keyword) => {
15 createPage({
16 path: `/keyword/${keyword}/`,
17 component: path.resolve('./src/layouts/keyword-page-layout.js'),
18 context: {
19 keyword: keyword,
20 }
21 })
22 })
23}
© 2025 K.S.K. All rights reserved., Built with Gatsby