【Gatsby.js】単一のjsonファイルを元に複数のページを生成する


Gatsby.jsを使って、jsonファイルから複数のページを生成する方法をまとめます。
Gatsby、情報自体はそこそこ豊富なんですが、日本語の情報が少ないですね。。

記事データをまとめたjsonファイルを作成

$ mkdir src/data
$ touch src/data/articles.json
src/data/articles.json
[
  {
    "slug": "how-to-use-gatsby",
    "title": "【Gatsby.js】「ここだけ押さえれば普通に使える」って知識をまとめてみた",
    "content": "Gatsby.jsでシンプルな静的サイトを作る際に必要な知識だけをまとめました。CMSとの連携等については今回は扱いません。本文テキスト本文テキスト本文テキスト本文テキスト本文テキスト本文テキスト",
    "tags": ["React", "Gatsby"]
  },
  {
    "slug": "learn-react",
    "title": "Reactの学習、今からやるならこうする",
    "content": "Reactの学習を初めて約2週間が経ちました。Railsの時と違って「とりあえずこれをやっておけば良い」ってものが見当たらずなかなか大変でしたが、試行錯誤の上色々と見えてきたのでまとめていきます。",
    "tags": ["React"]
  },
  {
    "slug": "restore-mac",
    "title": "Macの初期化→リストアを良い感じにする",
    "content": "Brewfile、Mackup、Docker、Dropboxを使って良い感じにリストアできる環境を作ったので、まとめます。以下の記事をめちゃくちゃ参考にしました。macOSでの開発環境を全部Docker化したらリストア時間が1時間半になった",
    "tags": ["Docker", "Brewfile", "Mackup"]
  }
]

記事のテンプレートページのベースを作成

$ mkdir src/templates
$ touch src/templates/article.js
src/templates/article.js
import React from "react"

export default () => (
  <>
    <h1>タイトル</h1>
    <p>本文</p>
    <span>タグ1</span>
    <span>タグ2</span>
  </>
)

記事を生成する処理を記述

$ touch gatsby-node.js
gatsby-node.js
const path = require("path")
const data = require("./src/data/articles.json")

exports.createPages = ({ actions }) => {
  const { createPage } = actions
  const template = path.resolve("./src/templates/article.js")
  data.forEach(article_object => {
    const path = `articles/${article_object.slug}`
    createPage({
      path, // 生成されるページのpath
      component: template, // ページのベースとなるテンプレート 
      context: article_object, // GraphQL経由で受け渡すデータのオブジェクト
    })
  })
}

GraphiQLを開き、データを取得するためのクエリを作成

gatsby developで開発サーバーを立ち上げ、ブラウザで http://localhost:8000/ にアクセスしてGraphiQLを開く。
allSitePage > edges > node > contextと順に開いていくと、titlecontenttagsが見つかるのでチェックを入れて実行し、欲しいデータが取得できることを確認。

GraphQLで取得したデータをテンプレートページに埋め込む

作成したクエリで必要なデータを取得し、テンプレートに埋め込みます。
GraphQLで取得したデータはdataというオブジェクトに格納されるので、そこから値を取り出して出力します。

src/templates/article.js
import { graphql } from "gatsby"
import React from "react"

export default ({ data }) => {
  const article = data.allSitePage.edges[0].node.context
  return (
    <>
      <h1>{article.title}</h1>
      <p>{article.content}</p>
      {article.tags.map(tag => (
        <span>{tag}</span>
      ))}
    </>
  )
}

export const query = graphql`
  query($path: String!) {
    allSitePage(filter: { path: { eq: $path } }) {
      edges {
        node {
          context {
            content
            tags
            title
          }
        }
      }
    }
  }
`

開発サーバーを再起動して確認

開発サーバーを再起動し、存在しないURLを入力して404ページを表示すると、ページ一覧に今作ったページが追加されていることが確認できます。

参考