Gatsby.js ブログへのタグ追加
こんにちは! うしじです。
本ブログにタグを追加したので、その方法について記載します。
参考:Gatsby公式ドキュメント
タグを追加するにあたり、下記のGatsbyのドキュメントを参考にしました。基本的には、下記のページに沿って対応すれば、タグを追加できます。
Step 1. Markdownファイルへのタグの追加
まず、ブログの各Markdownファイルにタグを追加します。本記事では下記のような記載です。
---
template: BlogPost
path: /blog-tags
date: 2020-05-19T15:00:00+09:00
title: Gatsby.js ブログへのタグ追加
thumbnail: /assets/202005/20200519/tag-3425877_1280.jpg
metaDescription: "GatsbyJSで作成したブログにタグを追加したので、その方法について記載しています。"
tags: ["GatsbyJS"]
---
Step 2. タグページ(/tags/{tag}) のテンプレート作成
src/templates/tags.js
ファイルを新たに作成し、タグページのテンプレートを作成します。
本ブログの場合は、fields.slugを作成していなかったので、Gatsbyのドキュメントの例(Creating Tags Pages for Blog Posts)から少し変更しています。
import React from "react"
import PropTypes from "prop-types"
import Helmet from 'react-helmet'
import { graphql } from "gatsby"
import Layout from "../components/layout"
import PostLink from "../components/post-link"
const Tags = ({ pageContext, data }) => {
const { tag } = pageContext
const { edges, totalCount } = data.allMarkdownRemark
const tagHeader = `"${tag}" 関連記事: ${totalCount}件`
const Posts = edges.map(edge => <PostLink key={edge.node.id} post={edge.node} />)
return (
<Layout>
<div>
<h1>{tagHeader}</h1>
<div className="grids">
{Posts}
</div>
</div>
</Layout>
)
}
Tags.propTypes = {
pageContext: PropTypes.shape({
tag: PropTypes.string.isRequired,
}),
data: PropTypes.shape({
allMarkdownRemark: PropTypes.shape({
totalCount: PropTypes.number.isRequired,
edges: PropTypes.arrayOf(
PropTypes.shape({
node: PropTypes.shape({
frontmatter: PropTypes.shape({
path: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
}),
}),
}).isRequired
),
}),
}),
}
export default Tags
export const pageQuery = graphql`
query($tag: String) {
allMarkdownRemark(
limit: 2000
sort: { fields: [frontmatter___date], order: DESC }
filter: { frontmatter: { tags: { in: [$tag] } } }
) {
totalCount
edges {
node {
id
excerpt(pruneLength: 250)
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
path
thumbnail
tags
}
}
}
}
}
`
Step 3. gatsby-node.js の更新
タグページのテンプレートを用いてページを作成するために、gatsby-node.js を更新します。これで、各タグのページを表示できるようになります。
本ブログの場合だと、このページのことです。
const path = require(`path`)
const _ = require(`lodash`)
exports.createPages = async ({ actions, graphql, reporter }) => {
const { createPage } = actions
const blogPostTemplate = path.resolve(`src/templates/blogTemplate.js`)
const tagTemplate = path.resolve(`src/templates/tags.js`)
const result = await graphql(`
{
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] }
limit: 1000
) {
edges {
node {
id
frontmatter {
path
tags
}
}
}
}
tagsGroup: allMarkdownRemark(limit: 2000) {
group(field: frontmatter___tags) {
fieldValue
}
}
}
`)
// Handle errors
if (result.errors) {
reporter.panicOnBuild(`Error while running GraphQL query.`)
return
}
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.frontmatter.path,
component: blogPostTemplate,
context: {}, // additional data can be passed via context
})
})
result.data.tagsGroup.group.forEach(tag => {
createPage({
path: `/tags/${_.kebabCase(tag.fieldValue)}`,
component: tagTemplate,
context: {
tag: tag.fieldValue,
},
})
})
}
Step 4. タグ一覧ページ作成
次に、src/pages/tags.js
ファイルを作成し、タグの一覧ページを作成します。
本ブログの場合だと、このページのことです。
import React from "react"
import PropTypes from "prop-types"
import kebabCase from "lodash/kebabCase"
import { Helmet } from "react-helmet"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
const TagsPage = ({
data: {
allMarkdownRemark: { group },
site: {
siteMetadata: { title },
},
},
}) => (
<Layout>
<Helmet>
<title>{title}</title>
</Helmet>
<div>
<h1>タグ一覧</h1>
<ul class="tags-list">
{group.map(tag => (
<li key={tag.fieldValue}>
<Link to={`/tags/${kebabCase(tag.fieldValue)}`}>
{tag.fieldValue} ({tag.totalCount})
</Link>
</li>
))}
</ul>
</div>
</Layout>
)
TagsPage.propTypes = {
data: PropTypes.shape({
allMarkdownRemark: PropTypes.shape({
group: PropTypes.arrayOf(
PropTypes.shape({
fieldValue: PropTypes.string.isRequired,
totalCount: PropTypes.number.isRequired,
}).isRequired
),
}),
site: PropTypes.shape({
siteMetadata: PropTypes.shape({
title: PropTypes.string.isRequired,
}),
}),
}),
}
export default TagsPage
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
allMarkdownRemark(limit: 2000) {
group(field: frontmatter___tags) {
fieldValue
totalCount
}
}
}
`
Step 5. 各ブログにタグを表示
最後に、下記の画像のように、各ブログにタグを表示させます。このタグは、各タグページへのリンクになっています。
import React from "react"
import { Link } from "gatsby"
import kebabCase from "lodash/kebabCase"
const PostLink = ({ post }) => (
<article className="card ">
<Link to={post.frontmatter.path}>
{!!post.frontmatter.thumbnail && (
<img src={post.frontmatter.thumbnail} alt={post.frontmatter.title + "- Featured Shot"} />
)}
</Link>
<header>
<h2 className="post-title">
<Link to={post.frontmatter.path} className="post-link">
{post.frontmatter.title}
</Link>
</h2>
<div className="post-meta">{post.frontmatter.date}</div>
<div className="post-meta">
{post.frontmatter.tags.map(tag => {
return <span className="post-tag"><Link
key={tag}
to={`/tags/${kebabCase(tag)}`}>
#{tag}
</Link></span>
})}
</div>
</header>
</article>
)
export default PostLink
これでタグの追加完了です!