Gatsby でもその他のブログツールのように、公開・公開設定を制御したい気持ちになりました。
公開設定の理想と現実
Gatsby で Markdown の記事などから GraphQL で公開データを取得してきたいとします。
ビルド環境に関係がない場合 GraphQL では filter
を使って以下のように取得できます。
exports.createPages = async ({ graphql, actions }) => {
...
const result = await graphql(`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 2000
filter: { frontmatter: { published: { eq: true } } }
) {
edges {
node {
fields {
slug
}
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
description
tags
}
}
}
}
}
`)
...
}
ここでは、markdown で書いた記事の frontmatter 部分に published
が定義されており、 true
か false
が入ることを想定しています。
filter で frontmatter の published が true に一致する場合の記事情報を取得する一番てっとりやすそうな方法です。
さて、ここで開発環境のときにのみ、 published: false
な記事をサイトに表示しておきたいとします。安易に考えると以下のように書きたくなります。
以下のコードは String interpolation is not allowed in graphql tag
と言われて動きません。
exports.createPages = async ({ graphql, actions }) => {
...
const result = await graphql(`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 2000
filter: ${process.env.NODE_ENV === 'production' ? { frontmatter: { published: { eq: true } } } : ''}
) {
edges {
node {
fields {
slug
}
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
description
tags
}
}
}
}
}
`)
...
}
どうやらタグ付きテンプレートリテラルの中で文字展開はできないようなので、その他の方法で実装するしかなさそうです。
こんな感じで nodes 配列を渡して published なものだけ取り出していきます。
const getOnlyPublished = edges =>
edges.filter(({ node: post }) => post.frontmatter.published)
process.env.NODE_ENV === 'production'
のときだけ上記関数を適用します。
このとき、GraphQL のクエリに published
を入れ忘れると、公開されてしまうので注意です。
...
const result = await graphql(`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC }
limit: 2000
) {
edges {
node {
fields {
slug
}
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
description
published
tags
}
}
}
}
}
`)
const allPosts = result.data.allMarkdownRemark.edges
const posts =
process.env.NODE_ENV === 'production'
? getOnlyPublished(allPosts)
: allPosts
...
いろんな starter もみてみましたが同じような実装でしたので、とりあえずこの方法で🥺。
Weekly number of page views since last build: 🥰