今までの記事
GatsbyJS v2 はじめの一歩 (1) 開発環境の立ち上げ
GatsbyJS v2 はじめの一歩 (2) 実際にページを作る
GatsbyJS v2 はじめの一歩 (3) ページにスタイルを当てる
GatsbyJS v2 はじめの一歩 (4) gatsby buildとデプロイ
GatsbyJS v2 はじめの一歩 (5) GraphQLによるデータ管理
GatsbyJS v2 はじめの一歩 (6) Source Pluginの利用
前回の記事ではSource Pluginを使って外部のデータをReactコンポーネントで使えるようにしました。ただし、前回のままだと一覧ページしか作っていません。ブログなどのウェブサイトを作ろうとすると、一覧ページだけではなく詳細ページも欲しくなると思います。
GatsbyJSのルーティングはsrc/pages以下のルーティングで決定されるということは以前説明しましたが、これでは外部データに依存する(例えば、記事詳細ページ)を作ることが出来ません。そこでgatsby-node.jsを利用することでGraphQLのデータを元にページを生成する方法も用意されています。
gatsby-node.jsはGatsbyJSの動作をカスタマイズするファイルです。このファイルの中でGatsbyJSのライフサイクルに合わせた関数をexportすることで希望の動作をさせることが出来ます。参考: Node APIs
今回はcreatePagesを使用します。この関数は動的にページを生成するための関数でプラグインによるソースの追加・加工が終わったタイミングで実行されます。
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
const postTemplate = path.resolve(`./src/templates/PostTemplate.jsx`)
return new Promise((resolve, reject) => {
graphql(`
allHnStory {
edges {
node {
id
title
score
order
domain
url
}
}
}
`).then(result => {
// GraphQLのデータを使ってページを追加する処理
result.data.allHnStory.edges.forEach(edge => {
const node = edge.node
createPage({
path: `/posts/${node.id}`,
component: postTemplate
})
})
resolve()
})
})
}
それでは順を追ってコードの解説をしていきます。
動的に追加するには次の手順を行います
まずはGraphQLでデータを取得します。次のコードをgatsby-node.jsに追加してください。
exports.createPages = ({ graphql }) => {
return new Promise((resolve, reject) => {
graphql(`
{
allHnStory {
edges {
node {
id
title
score
order
domain
url
}
}
}
}
`).then(result => {
console.log(JSON.stringify(result, null, 4))
resolve()
})
})
}
このコードを保存して、gatsby develop
を実行するとビルド中に以下の出力が表示されます。無事にデータが取得されconsole.logで表示されました。
次に動的に作成するページのテンプレートを作成します。Gatsbyでは動的に生成されるファイルはsrc/templates/
以下に保存することが通例となっています。
今回は src/templates/story.jsx
として次のファイルを追加します。
import React from "react"
export default () => {
return (
<div>This is story page</div>
)
}
最後にGraphQLで取得したデータと、作成したテンプレートを紐づけます。ページを作成するためのメソッドがactions.createPageです。path(サイト上のパス)とcomponent(適用したいテンプレートのファイルパス)とcontext(ページに渡したい変数のオブジェクト)を引数とするメソッドです。
const path = require('path')
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return new Promise((resolve, reject) => {
graphql(`
{
allHnStory {
edges {
node {
id
title
score
order
domain
url
}
}
}
}
`).then(result => {
result.data.allHnStory.forEach(storyEdge => {
const node = storyEdge.node
const path = `/stories/${node.id}`
console.log(path)
createPage({
path: path
component: path.resolve(`./src/templates/story.js`),
context: {
id: node.id
}
})
} )
resolve()
})
})
}
この状態で再度gatsby devevelop
を実行しましょう。実行時のログにpathを表示しているので、それをURL欄に入力すると、Templateで定義したページが表示されます。
TODO: スクショ
この状態ではまだ動的にURLに対応するページが生成されただけで、ページの内容にデータが反映されていません。ページ内にデータを反映させていきましょう。src/template/story.jsx
を次のように編集します。
graphQLでeq: $idとあるのは、createPageで渡したcontext内にあるidです。idと一致するhnStoryを取得するというクエリを投げています。この状態でブラウザを開くと、個別のデータが入ったページが表示されます。
import React from "react"
import { graphql } from "gatsby"
export default ({ data }) => {
const story = data.hnStory
return (
<div>
<h1>{story.title}</h1>
</div>
)
}
export const query = graphql`
query($id: String!) {
hnStory(fields: { id: { eq: $id } }) {
id
title
score
order
domain
url
}
}
`
このような手順で、動的にページを作成していくことができます。多少長い手順となりましたが、データとテンプレートの結合度が低い状態で実装していけることが分かると思います。
ここ最近、Web技術を利用した画像生成に興味があります。本記事では、日本語における表現の一種である縦書きに焦点を当て、Web技術を使った縦書きを含む画像生成方法についての調査をまとめました。 > 現
追記(2022/12/29): 問い合わせに対応する窓口をTwitterに統一したいので、フォームページは削除しました。 当ブログは静的サイトホスティングサービスのNetlifyでホスティングされ
毎年10月に開催されるHacktoberfestに参加しました。このイベントはOSSへの貢献を行い、期間中に規定数(4つ)の貢献を行った人に特典がプレゼントされるものになっています。 自分はドキュメ