GatsbyJSブログにタグページを追加した
2020-05-04Content
はじめに
おはようございます!こんにちは!こんばんは!
麻雀と芝生大好きおじさんことのふのふ(@rpf_nob)です!!
今回はGatsbyJSブログにタグページを追加して、タグごとに記事一覧が表示できるようにします。
基本的には公式ページの内容通りやればできます。
前提
このブログはGatsbyJSのgatsby-starter-blogのテンプレートから作成しています。
記事のマークダウンファイルにタグを追加する
各記事のマークダウンファイルの上部のメタ情報の部分に[tags]を追加します。複数ある場合は[,]で連結して記載します。
---
title: GatsbyJSブログにタグページを追加した
date: "2020-05-04"
description: 今回はGatsbyJSブログにタグページを追加して、タグごとに記事一覧が表示できるようにします。
slug: 2020-05-04/gatsby-tag
tags: [GatsbyJS]---
GraphQLのクエリを記述して投稿記事のタグを全て取得する
GraphiQL(http://localhost:8000/___graphql)にアクセスして次のクエリを実行すれば、 下のような結果が返ってくるはずです。投稿記事を[tags]でグループ化して、各tagの投稿数が[totalCount]として返ってきます。
{
allMarkdownRemark {
group(field: frontmatter___tags) {
tag: fieldValue
totalCount
}
}
}
{
"data": {
"allMarkdownRemark": {
"group": [
{
"tag": "GatsbyJS",
"totalCount": 5
},
{
"tag": "Netlify",
"totalCount": 1
},
{
"tag": "エンジニア",
"totalCount": 1
},
{
"tag": "コロナ",
"totalCount": 1
},
{
"tag": "テレワーク",
"totalCount": 1
},
{
"tag": "肥料",
"totalCount": 1
},
{
"tag": "芝生",
"totalCount": 1
}
]
}
}
}
タグページのテンプレートを作成する
[src/templates/tags.js]を新規作成し、タグページのテンプレートを作成していきます。
基本的にはトップページと同じような見た目にしたいので、ソースコードもほとんど同じになります。
コンポーネント化して共通化したいですね・・・
import React from "react";
import Bio from "../components/bio";
import Layout from "../components/layout";
import SEO from "../components/seo";
import { rhythm } from "../utils/typography";
// Components
import { Link, graphql } from "gatsby";
const Tags = ({ pageContext, data, location }) => {
const { tag } = pageContext;
const { edges, totalCount } = data.allMarkdownRemark;
const author = data.site.siteMetadata.author.name;
const tagHeader = `[${tag}]タグの記事一覧(全${totalCount}件)`;
return (
<div>
<Layout location={location} author={author}>
<SEO
title={`Tag: ${tag}`}
description={`${tag}タグを含む記事の一覧ページです`}
/>
<Bio />
<h2>{tagHeader}</h2>
{edges.map(({ node }) => {
const title = node.frontmatter.title || node.fields.slug;
return (
<article key={node.fields.slug}>
<header>
<h3
style={{
marginBottom: rhythm(1 / 4),
}}
>
<Link
style={{ boxShadow: `none` }}
to={node.frontmatter.slug}
>
{title}
</Link>
</h3>
<small>{node.frontmatter.date}</small>
</header>
<section>
<p
dangerouslySetInnerHTML={{
__html: node.frontmatter.description || node.excerpt,
}}
/>
</section>
</article>
);
})}
</Layout>
</div>
);
};
export default Tags;
export const pageQuery = graphql`
query($tag: String) {
site {
siteMetadata {
title
author {
name
}
}
}
allMarkdownRemark(
limit: 2000
sort: { fields: [frontmatter___date], order: DESC }
filter: { frontmatter: { tags: { in: [$tag] } } }
) {
totalCount
edges {
node {
fields {
slug
}
frontmatter {
title
date(formatString: "YYYY-MM-DD")
description
slug
}
}
}
}
}
`;
ページをレンダリングする
[gatsby-node.js]に↑で作成したテンプレートを使用して、ページをレンダリングするように変更します。
以下のように変更すれば、[/tags/タグ名]に各タグの記事一覧ページが作成されます。
const path = require(`path`);
const _ = require("lodash");
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions;
const blogPost = path.resolve(`./src/templates/blog-post.js`);
const tagTemplate = path.resolve(`./src/templates/tags.js`); const result = await graphql(
` {
posts: allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 1000
) {
edges {
node {
fields {
slug
}
frontmatter {
title
slug
}
}
}
}
tags: allMarkdownRemark(limit: 1000) {
group(field: frontmatter___tags) {
fieldValue
}
}
}
`
);
if (result.errors) {
throw result.errors;
}
const posts = result.data.posts.edges;
posts.forEach((post, index) => {
const previous = index === posts.length - 1 ? null : posts[index + 1].node;
const next = index === 0 ? null : posts[index - 1].node;
createPage({
path: `/${post.node.frontmatter.slug}/`,
component: blogPost,
context: {
slug: post.node.fields.slug,
previous,
next,
},
});
});
const tags = result.data.tags.group; tags.forEach(tag => { createPage({ path: `/tags/${_.kebabCase(tag.fieldValue)}/`, component: tagTemplate, context: { tag: tag.fieldValue, }, }); });};
これで以下のようなタグページが作成されます。
記事にタグページジャンプ用のタグをつける
最後に記事ページにタグページへのジャンプするためのタグをつけていきます。
タグ表示用のコンポーネントを作成する
propsで記事のタグのリストを渡してもらい、それを使ってタグページにジャンプできるようにします。
import React from "react";
import { Link } from "gatsby";
import _ from "lodash";
const Tag = props => {
return (
<div className="tag">
{props.tags.map((tag, index) => {
return (
<Link
to={`/tags/${_.kebabCase(tag)}/`}
key={index}
className="tag__list"
>
{tag}
</Link>
);
})}
</div>
);
};
export default Tag;
作成したタグコンポーネントを目次の前に挿入
[src/templates/blog-post.js]の目次の前に上で作ったTagコンポーネントを挿入します。
GraphQLで取得したdata.frontmatter.tagsをpropsとして渡します。
<header>
・・・省略
</header>
<Tag tags={post.frontmatter.tags} />
<Toc data={data.markdownRemark.tableOfContents} />
<section/>
スタイル調整
あとは好きなスタイルを付けて完成となります。
.tag {
margin-bottom: 20px;
&__list {
margin-right: 10px;
box-shadow: none;
border: 1px solid #555;
padding: 0 5px;
border-radius: 3px;
color: blue;
background-color: #f2f2f2;
}
}
まとめ
今回はGatsbyJSブログにタグページを追加して、タグごとに記事一覧が表示できるようにしました。
記事が増えてきたときに、タグページがあると読みたいタグを一気に見れるのでいいですよね。
他にもGatsbyJSのブログカスタマイズをいろいろやっているので、以下もあわせてご覧いただければと思います。
最後まで見ていただきありがとうございます!!