Gatsbyjs のバージョン2.26.0から利用できるようになった File System Route API。データをもとにしたページ生成をシンプルに実現できるとても便利な機能ですので、書籍『Webサイト高速化のための静的サイトジェネレーター活用入門』のサンプルを利用して確認してみます。
書籍では Contentful に用意したデータをもとに、gatsby-node.js で /blog/post/ の中に各ポストのページを生成しています。
そこで、/blog/post2/ というフォルダを用意して各ポストのページを生成してみます。
まずは、/src/pages/blog/post2/ の中に、{ContentfulBlogPost.slug}.js というファイルを作成し、その中身はこんな感じにしておきます。
import React from "react"
const BlogPost = () => (
<div>Hello world!</div>
)
export default BlogPost
この状態で gatsby develop を実行すると、/blog/post2/ の中にページが生成されているのが確認できます。
やっていることは非常にシンプルです。
{ContentfulBlogPost.slug}.js というファイル名によって、
allContentfulBlogPost {
nodes {
slug
id
}
}
というクエリが処理されます。
ここでは書籍サンプルと同様に各記事の slug を取得し、それをもとにURLを生成しています。
各ページは {ContentfulBlogPost.slug}.js をテンプレートとして生成されます。
テンプレートではこのクエリの結果をもとに処理することになります。今回の例では slug と id を使って処理を組み立てて行くことになります。
クエリの結果は、props.params によってテンプレートの中で利用することができます。例えば、{ContentfulBlogPost.slug}.js を次のように書き換えると、各ポストに slug を表示することができます。
import React from "react"
const BlogPost = ({ params }) => {
console.log(params)
return (
<div>{params.slug}</div>
)
}
export default BlogPost
ただし、params の中には id が含まれていないことも確認できます。
id はクエリのフィルタリングに利用することが想定されており、更に書き変えて、
import React from "react"
import { graphql } from "gatsby"
const BlogPost = ({ params, data }) => {
console.log(params)
return (
<div>{data.contentfulBlogPost.title}</div>
)
}
export const query = graphql`
query($id: String) {
contentfulBlogPost(id: { eq: $id }) {
title
content {
content
}
}
}
`
export default BlogPost
といった形で利用することになります。
gatsby-node.jsを触ることなく手軽にページを生成することができるので、商品ページなどを生成する場合には非常に便利です。
ただし、現時点では createPage のように pageContext を通してオブジェクトを渡すといったことはできませんので、ページネーションなどが必要な場合は、ちょっと検討が必要でしょう。
Can I pass custom properties into pageContext?
When using the
https://www.gatsbyjs.com/blog/fs-route-api/createPage
function you’re able to pass custom properties into thecontext
object of each page. This isn’t possible at the moment.
ファイル名によるクエリの設定に関しては、公式のページに詳しく書かれていますので参照してください。