Gatsby で gatsby-theme-blog を使うときの tips

JavaScriptJamstackSSGReactGatsby

gatsby-theme-blog

Gatsby 公式のブログ用テーマ gatsby-theme-blog を使うときの tips 集です。

追記 2020/07/29: この説明は gatsby-theme-blog のバージョン 1.x 系に対するものです。 2020 年 7 月にリリースされた 2.x にはあてはあまらない部分もありますのでご注意ください。

Gatsby の theme システムには WordPress 等旧来の CMS によくある拡張機能が備わっているのですが、 gatsby-theme-blog の場合はおそらく大がかりな拡張はせずほぼそのまま使うものとして作られている感じがします。 あるいは gatsby-theme-blog は単純に reference implementation なのかもしれません。 そんな gatsby-theme-blog を私なりに工夫して使い倒してみたので、その tips をまとめました。

できるだけ gatsby-theme-blog に特化したことだけを書き、 Gatsby を利用する際に一般的な tips は書かないようにします。

尚本記事執筆時の各ライブラリの最新バージョンは次のとおりです。

  • react: 16.12.0
  • gatsby: 2.19.5
  • gatsby-theme-blog: 1.2.32

最初にかんたんに用語の説明をします。

用語の説明

Gatsby とは?

Gatsby は React ベースのウェブサイト・ウェブアプリ制作用のフレームワークです。

カテゴリとしては「スタティックサイトジェネレータ」(静的サイトジェネレータ)や「 Jamstack フレームワーク」等に分類されるでしょうか。

追記 2020/05/26: 静的サイトジェネレーターや Jamstack に興味がある方には次の記事がご参考になるかと思います。

gatsby-theme-blog とは?

gatsby-theme-blog (The Gatsby Blog theme) は Gatsby 公式のブログ作成用テーマです。

そのまま使った場合、ページャの無い投稿の一覧ページと詳細ページだけからなる非常にシンプルなブログを構築できます。

Gatsby の theme システムには他のテーマを「ベーステーマ」として利用できる仕組みが用意されています。 gatsby-theme-blog の場合は gatsby-theme-blog-core がベーステーマになっています。 gatsby-theme-blog-core も Gatsby 公式のテーマです。

では本題です。

gatsby-theme-blog を使うときの tips

tips 01. gatsby-theme-blog を使ってブログ制作を始めたい

gatsby-theme-blog を使ってブログを始めるときは、公式の説明のとおりスターター gatsby-starter-blog-theme を使う方法がかんたんです。

gatsby new my-blog https://github.com/gatsbyjs/gatsby-starter-blog-theme

my-blog の部分にはプロジェクトルートとなるディレクトリ名を渡します。

gatsby new コマンドを実行したら、ファイル gatsby-config.js を編集して gatsby-theme-blog のテーマオプションと siteMetadata を設定すれば、後は .md ファイルを追加していくだけですぐにブログを作り始められます。

本記事執筆時点で gatsby-theme-blog のテーマオプションは次のとおりです。

  • basePath: ブログのルート URL 。ここに全投稿の一覧ページが表示される。デフォルトは /
  • contentPath: ブログの投稿の .md ファイルを配置するパス。デフォルトは content/posts
  • assetPath: アセットファイルを配置するパス。デフォルトは content/assets
  • mdx: gatsby-plugin-mdx を設定するかどうか。デフォルトは true

基本的にはデフォルト値のままで使えます。

siteMetadata の有効な要素には次のものがあります。

  • title: ブログのタイトル。ヘッダーに表示される。
  • author: avatar の alt や OGP の twitter:creator タグの値に使われる。
  • description: meta description タグの値。
  • social: GitHub や Twitter 等のアカウント。 2 つの要素 nameurl を持つオブジェクトの配列を入れる。

.md ファイルでは frontmatter が利用できます。 frontmatter とは、次に示すような、 .md ファイルの先頭に置けるメタ情報の記述です。

---
title: こんにちは
slug: /post/hello-world
date: 2020-05-27
keywords:
  - あいさつ
  - 日本語
---

これは本文です。

frontmatter 参考:

tips 02. 一覧ページのパスを変えたい

ブログ投稿の一覧ページのパスを変えたいときは、テーマオプション basePath を変更すれば OK です。

// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-theme-blog`,
      options: {
        basePath: `/archive`,
      },
    },
  ],
}

tips 03. 新しいノードタイプを追加したい

デフォルトで用意されている「ブログ投稿」以外のノードタイプを追加したいときは、通常の Gatsby サイトと同じように、 gatsby-node.js 内に createSchemaCustomization() を書いてその中で createTypes() を使ってノードタイプを定義すれば OK です。

次のコードは StaticPage というインタフェースと MdxStaticPage というノードタイプを定義するサンプルです:

exports.createSchemaCustomization = ({ actions, schema }) => {

  // インタフェース `StaticPage` とタイプ `MdxStaticPage` を定義する
  createTypes(`
    interface StaticPage @nodeInterface {
      id: ID!
      title: String!
      slug: String!
      excerpt: String!
      body: String!
    }
  `)

  createTypes(
    schema.buildObjectType({
      name: `MdxStaticPage`,
      fields: {
        id: { type: `ID!` },
        title: { type: `String!` },
        slug: { type: `String!` },
        excerpt: {
          type: `String!`,
          args: {
            pruneLength: {
              type: `Int`,
              defaultValue: 140,
            },
          },
          resolve: mdxResolverPassthrough(`excerpt`),
        },
        body: {
          type: `String!`,
          resolve: mdxResolverPassthrough(`body`),
        },
      },
      interfaces: [`Node`, `StaticPage`],
    })
  )

}

tips 04. 固定ページを作りたい 

固定ページを作りたいときは、通常の Gatsby サイトと同じように gatsby-node.js 内に createPages() を書いて、その中で createPage() でページを追加すれば OK です。

ブログ投稿の一覧ページ・詳細ページと同じレイアウトを適用したい場合は、パッケージ gatsby-theme-blog 内の src/components/ 以下の posts.jspost.js を参考にします。

post.js:

import React from "react"
import { Styled, css } from "theme-ui"

import PostFooter from "../components/post-footer"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { MDXRenderer } from "gatsby-plugin-mdx"

const Post = ({
  data: {
    post,
    site: {
      siteMetadata: { title },
    },
  },
  location,
  previous,
  next,
}) => (
  <Layout location={location} title={title}>
    <SEO title={post.title} description={post.excerpt} />
    <main>
      <Styled.h1>{post.title}</Styled.h1>
      <Styled.p
        css={css({
          fontSize: 1,
          mt: -3,
          mb: 3,
        })}
      >
        {post.date}
      </Styled.p>
      <MDXRenderer>{post.body}</MDXRenderer>
    </main>
    <PostFooter {...{ previous, next }} />
  </Layout>
)

export default Post

tips 05. プロフィールコンポーネントのレイアウトを変えたい

プロフィールコンポーネントのレイアウトを変えたいときは、 gatsby-theme-blogBio コンポーネントをシャドーイングで変更すれば OK です。

Bio コンポーネントは gatsby-theme-blog パッケージの中の src/components/bio.js で定義されています。

ちなみに、プロフィールの本文だけを変更したいときは、その隣にある BioContent (bio-content.js) をシャドーイングします。 プロフィール画像(「アバター」)を設定したいときは、 content/assets/ 以下に avatar.[jpeg|jpg|gif|png] (拡張子はいずれか)というファイル名で画像ファイルを設置すれば OK です。

tips 06. タグページ(タグ別の投稿一覧ページ)を作りたい

gatsby-theme-blog では frontmatter でのタグをサポートしていますが、タグページ(タグ別の投稿一覧ページ)が自動で作られるわけではありません。 タグページを作りたい場合は自分で作成する必要があります。

タグページを追加するには、一般に Gatsby でページを追加したいときと同じように createPages() の中で createPage() を書けば OK です。

タグは単純な文字列なので、タグデータは投稿のノードタイプ BlogPost から group を使って抽出できます。

exports.createPages = async ({ graphql, actions, reporter }) => {
  const { createPage, createRedirect } = actions

  const result = await graphql(`
    {
      allBlogPost {
        group(field: tags) {
          name: fieldValue
          totalCount
        }
      }
    }
  `)

  if (result.errors) {
    reporter.panic(result.errors)
  }

  const tags = result.data.allBlogPost.group
  tags.forEach(tag => {
    createPage({
      path: `/tags/${slugify(tag.name)}/`,
      component: PostTagPageTemplate,
      context: {
        name: tag.name,
      },
    })
  })

}

tips 07. 投稿一覧ページをカスタマイズしたい

投稿一覧ページをカスタマイズしたいときは、 gatsby-theme-blogposts.js コンポーネントをシャドーイングします。 posts.jsgatsby-theme-blog パッケージ内の src/components/ 以下にあります。

投稿一覧ページのテンプレートだけでなく GraphQL クエリごと丸ごと変更したいときは、 gatsby-theme-blog-coreposts-query.js テンプレートをシャドーイングします。

posts-query.jsgatsby-theme-blog-core パッケージ内の src/templates/ 以下にあります。

tips 08. 投稿詳細ページをカスタマイズしたい

投稿詳細ページも投稿一覧ページと同様にカスタマイズできます。

テンプレートをカスタマイズしたしときは、 gatsby-theme-blogpost.js コンポーネントをシャドーイングします。 post.jsgatsby-theme-blog パッケージ内の src/components/ 以下にあります。

投稿一覧ページのテンプレートだけでなく GraphQL クエリごと丸ごと変更したいときは、 gatsby-theme-blog-corepost-query.js テンプレートをシャドーイングします。

post-query.jsgatsby-theme-blog-core パッケージ内の src/templates/ 以下にあります。

tips 09. 日付のフォーマットを変更したい

投稿一覧ページと投稿詳細ページの投稿日付のフォーマットは、デフォルトでは日本人に馴染みの薄い 月 日, 年 になっています。 これを変更したいときは、 posts-query.jspost-query.js をシャドーイングして GraphQL クエリを変更します。

例えば次のようにすると 2020/05/27 といったフォーマットにできます。

export const query = graphql`
  query CustomedPostPageQuery($id: String!, $previousId: String, $nextId: String) {
    site {
      siteMetadata {
        title
        social {
          name
          url
        }
      }
    }
    blogPost(id: { eq: $id }) {
      id
      excerpt
      body
      slug
      title
      tags
      keywords
      date(formatString: "YYYY/MM/DD")
    }
  }
`

tips 10. オリジナルの 404 ページを設定したい

オリジナルの 404 ページを設定したいときは、 Gatsby サイトでの一般的な方法と同じで、 src/pages/404.js ファイルを作成すれば OK です。 このパス・名前でファイルを作成すれば Gatsby が自動的にそれを 404 ページに使用してくれます。

tips 11. CSS のスタイルを変更したい

gatsby-theme-blog はデフォルトで gatsby-plugin-theme-ui を通じて theme-ui を利用して CSS スタイルを作っています。

この CSS のスタイルを変更したいときは、 gatsby-plugin-theme-ui のコンポーネントをシャドーイングします。 変更したい箇所によっては gatsby-theme-bloggatsby-plugin-theme-ui のコンポーネントをシャドーイングしている部分をさらにシャドーイングする必要があります。

tips 12. テーマが生成するページにコンテキスト変数を追加したい

gatsby-theme-blog または gatsby-theme-blog-core が提供するページのコンテキスト変数を追加したいときは、 onCreatePage() を使います。

ただし、すでに作られたページに後からコンテキスト変数を追加することはできないので、 onCreatePage() の中で deletePage() で元のページをいったん削除してから、コンテキスト変数を追加した形で createPage() してページを再追加する必要があります。

const merge = require(`deepmerge`)

exports.onCreatePage = async ({ page, actions, getNode }) => {
  const { createPage, deletePage } = actions

  if (/* 対象ページでのみ true を返す条件式 */) {
    const node = getNode(page.context.id)
    deletePage(page)
    createPage(
      merge(
        {
          context: {
            tags: node.tags,
          },
        },
        page
      )
    )
  }
}

tips 13. <html>lang 属性を ja に変更したい

gatsby-theme-blog のデフォルトのテンプレートでは htmllang 属性が en になっています。

<html lang="en">

これは gatsby-theme-blogseo.js コンポーネントをシャドーイングすると変更することができます。

lang 属性を変更するためだけに seo.js をシャドーイングするのは面倒なので、今後 gatsby-theme-blog のメンテナンスが継続されれば lang 属性はテーマオプションで設定できるようになると思います)

tips 14. 画像が二重に表示されるバグをどうにかしたい

追記 2020/04/19: このバグは解消されたようです。

状況によっては gatsby-theme-blog を使っていると markdown 内の画像が 2 重に表示されてしまうことがあります。

当面の対応としては、 gatsby-config.jsgatsby-remark-images を明示的に読み込むことでバグを回避することができます。

関連イシュー:

tips 15. ソースコードを確認したい

gatsby-theme-blog を使うときにシャドーイングが必要になった場合なんかには、 gatsby-theme-blog のコードを確認しないと進められないことがあります。

gatsby-theme-blog のコードは Gatsby 公式の themes というリポジトリの中にあります( 2020 年 07 月に Gatsby 本体のリポジトリから分離されました)。

gatsby-theme-blog の親テーマである gatsby-theme-blog-core のコードも同じく Gatsby 本体のリポジトリの中にあります。

ということで、 Gatsby で gatsby-theme-blog を使うときの小ネタ集でした。

追記 2020/05/26

gatsby-theme-blog もその親テーマである gatsby-theme-blog-core も活発に開発が進んでおり、テーマオプションで設定できる項目や post ノードのフィールドがどんどん追加されていっています。 利用の際はぜひ最新の README も確認するようにしてください:


アバター
後藤隼人 ( ごとうはやと )

Python や PHP を使ってソフトウェア開発やウェブ制作をしています。詳しくはこちら