投稿した記事にタグ付けするような機能は是非とも欲しいと思っていた。こちらもページネーションの記事同様、実装がさほど難しくなさそうだったのでプラグインではなく自前で実装した。
用意するもの
- キーワード一覧ページ
- キーワードに紐づく記事一覧ページ
- レイアウト
- URL
基本的にやることや用意するものはページネーションの記事と同じ。内部的に発行する GraphQL が多少違うだけ。
設計
Markdown内のキーワードの指定の仕方
1---2title: タイトル3date: 2021-03-264keywords:5 - keyword_16 - keyword_27---89## ヘッダ1011ここから記事本文
各記事のメタデータ記載部分に keywords という項目を作ることで記事にキーワードを付与する事ができるようにする。
キーワード一覧ページを作る
キーワード一覧ページは表示するコンテンツによって URL が変わったりしないためページコンポーネントとして作成した。
pages/keywords.js
1import React from "react"2import { Link, graphql } from "gatsby"34import GlobalLayout from "../layouts/global-layout"5import SEO from "../components/seo"678const 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}2728export const query = graphql`29 {30 allMdx {31 group(field: frontmatter___keywords) {32 fieldValue33 totalCount34 }35 }36 }37`383940export default Keywords
キーワードに紐づく記事一覧ページ
キーワード一覧ページが出来たら、今度はそのページから遷移する先の「選択されたキーワードに紐づく記事一覧ページ」が必要となる。
レイアウト
こちらは選択されたキーワードによって URL が変わるため gatsby-node.js で URL を作らないといけない。その際にレイアウトファイルを結びつける必要があるため先にレイアウトファイルを作る。
PostExcerpt コンポーネントは記事の見出し用コンポーネントで、トップページやページネーション内でも使っているもの。
layouts/keyword-page-layout.js
1import React from "react"2import {graphql} from "gatsby"34import GlobalLayout from "./global-layout"5import SEO from "../components/seo"6import PostExcerpt from "../components/post-excerpt"78const 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 <PostExcerpt17 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}2829export 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 title39 date40 }41 slug42 excerpt43 }44 }45 }46}47`4849export default KeywordPageLayout
URL 作成
つづいて URL 作成。一部抜粋したものだが下記のような感じ。これにより /keyword/<キーワード>/ という URL に対し、上で作った layouts/keyword-page-layout.js が対応してくれるようになる。
gatsby-node.js
1exports.createPages = async ({ graphql, actions }) => {2 const { createPage } = actions3 await createKeywordPages(graphql, createPage)4}56async 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}