gatsby+cmsで動的にページを生成

contentful上で記事を作成

割愛

GraphQLでcontentfulのデータを扱えるようにする

$ yarn add gatsby-source-contentful
Bash
// gatsby-config.js
...
		`other-plugin-hoge`,
		{
			resolve: `gatsby-source-contentful`,
			options: {
				spaceId: process.env.CONTENTFUL_SPACE_ID,
				accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
				host: process.env.CONTENTFULHOST,
			},
		},
	],
}
JavaScript
http://localhost:8000/___graphql を開いてallContentful~contentful~ という項目が増えていることを確認。

記事のテンプレートファイルを作成

$ mkdir src/templates
$ touch src/templetes/blogpost-template.js
Bash
https://localhost:8000/__graphql を開いてクエリを作成し、テンプレートファイル下部に貼り付け。
// src/templates/blogpost-template.js
import React from "react"
import { graphql } from "gatsby"

export default({ data }) => (
	<div>
		<h1>{data.contentfulBlogPost.title}</h1>
	</div>
)

export const query = graphql`
	query {
		contentfulBlogPost {
			title
		}
	}
`
JavaScript

gatsby-node.jsを作成

$ touch gatsby-node.js
Bash
Gatsbyがページを生成する際、特定のタイミングやイベントに合わせて処理をさせたいケースがあります。そうした処理を設定するのがgatsby-node.jsです。
GatsbyNodeAPIとして様々なAPIが用意されており、関数の形でexportすることで利用します。ここではcreatePagesを使います。
//gatsby-node.js
const path = require("path")

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

クエリを生成する

allContentfulBlogPost > edges > node > id, slug あたりにチェックを入れてクエリを生成

クエリを追加する

生成したクエリをgatsby-node.jsに追加。クエリの結果はblogresultに受け取る。クエリでエラーが発生した場合のメッセージ表示処理も合わせて実装。
//gatsby-node.js
const path = require("path")

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

	const blogresult = await graphql(`
		query {
			{ここにクエリをペースト}
		}
	`)
	if(blogresult.errors) {
		reporter.panicOnBuild(`GraphQLのクエリでエラーが発生しました`)
		return
	}
}
JavaScript

createPageでページを生成する

クエリで取得したデータからforEachメソッドで各記事のデータを取り出し、ページを生成。ページの生成にはcreatePagesを使って、以下のように設定。

path

生成するページのパス。ここではblog/post/スラッグ をセット

component

生成に使用するテンプレート。gatsby-node.jsからの相対パスで指定。ここではblogpost-template.jsを指定。
//gatsby-node.js
const path = require("path")

exports.createPages = async({ graphql, actions, reporter }) => {
	...
	const blogresult = ...
	if(blogresult.errors) {
		...
	}
	blogresult.data.allContentfulBlogPost.edges.forEach(({ node })) => {
		createPage({
			path: `/blog/post/${node.slug}`
			component: path.resolve(`./src/templates/blogpost-template.js`)
		})
	}
}
JavaScript
これで記事ページが生成される。開発サーバーを起動し直して404ページを表示すると、ページが追加されていることが確認できる。
ただしこの段階では、全てのページで同じ内容が表示されてしまう。

記事ごとにデータを読み込んでページを生成

記事ごとに別のデータを読み込むため、テンプレート(blogpost-template.js)に各記事のIDを送り、そのIDを使ってデータを取得するように修正する。
//gatsby-node.js
	blogresult.dta.allContentfulBlogPost.edges.forEach(({ node })) => {
		createPage({
			path: `/blog/post/${node.slug}`
			component: path.resolve(`./src/templates/blogpost-template.js`),
			context: {
				id: node.id,
			}
		})
	}
}
JavaScript
contextで指定されたデータは、$をつけることでクエリの変数として扱うことができる。
テンプレート(blogpost-template.js)側のクエリを、受け取った変数を使ったクエリに修正。
// src/templates/blogpost-template.js
export const query = graphql`
	query($id: String!){
		contentfulBlogPost(id: { eq: $id }){
			title
		}
	}
`
JavaScript