環境
- Gatsby 4.13.0
以前使用していたスターターでは、 frontmatter に draft: true
と書いておけばプロダクションビルドにはその記事は含まれなかった(はず)。
いま使用している gatsbyjs 公式のスターターだとそれが実装されていない。
現時点で未公開のこのブログ、公開するには書き換えのドラフトを公開しないようにする必要があるなと思ってやってみた。
参考にしたページでは NODE_ENV
という環境変数が production
かどうかを基準にしていたが、この記事ではドラフト記事を生成するかどうかの環境変数を用意してその値を見て生成するかどうかを変更するようにする。
まずは環境変数の使い方。
環境変数を設定する
公式のページを参考に環境変数の使い方を確認する。
https://www.gatsbyjs.com/docs/how-to/local-development/environment-variables/
こちらのページによると、 gatsby-config.js
に以下のように記述しておくと、
- development 環境では
.env.development
- production 環境では
.env.production
がそれぞれ読み込まれて、 gatsby-*.js
で使えるようになる。
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
})
環境変数を読み取る
.env に記述する際には名前の付け方に注意する必要がある。
GATSBY_
で始まらない環境変数はブラウザ環境(src/pages/index.js など) では使用できない。
今回は環境変数で指定した値を src/pages/index.js
でフィルタに使用しようとしているので GATSBY_
で始める必要がある。
フィルタを実装する
必要なものが整理できたので、実装していく。
- 環境変数を設定
- 環境変数読み込み
- フィルタリングの実装
という手順で実装する。
まず環境変数の設定。
.env.development
と .env.development
を作成。
.env.development
のみ以下の内容を記述する。
GATSBY_GENERATE_DRAFT=yes
次に gatsby-config.js
で .env ファイルの読み込みを行うようにする。
gatsby-config.js
の先頭に以下を記述。
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
})
やっとフィルタを実装していく。
まずは記事ページを生成しないようにする。
gatsby-node.js
を編集して、条件に応じてフィルタを変更する。
// Define a template for blog post
const blogPost = path.resolve(`./src/templates/blog-post.js`)
+ // 未設定の場合はドラフトを出力したくないので
+ // GATSBY_GENERATE_DRAFT は "no" にデフォルトする。
+ const shouldCreateDraftPages
= (process.env.GATSBY_GENERATE_DRAFT ?? "no") === "yes";
+
+ // フィルタ
+ const filter = shouldCreateDraftPages
+ ? ''
+ : 'filter: { frontmatter: { draft: { ne: true } } }';
+
// Get all markdown blog posts sorted by date
const result = await graphql(
`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: ASC }
+ ${filter}
limit: 1000
) {
nodes {
これで .env ファイルに書いた GATSBY_GENERATE_DRAFT
が yes 以外の場合に記事ページが生成されなくなった。
一覧ページ (src/pages/index.js
) も同じように実装しようとしたら、以下のようなエラーになった。
String interpolations are not allowed in graphql fragments. Included fragments should be referenced as `...MyModule_foo`.
よくわからなかったがダメなものはダメということで、とりあえず graphql の結果を使う際に frontmatter の値を見てフィルタするようにした。
// 未設定の場合はドラフトを出力したくないので
// GATSBY_GENERATE_DRAFT は "no" にデフォルトする。
const shouldShowDraftPages =
(process.env.GATSBY_GENERATE_DRAFT ?? "no") === "yes"
const posts = shouldShowDraftPages
? data.allMarkdownRemark.nodes
: data.allMarkdownRemark.nodes.filter($0 => {
// frontmatter に draft が未設定の場合は
// ドラフトとして扱いたいので true にデフォルトする。
return ($0.frontmatter.draft ?? true) === false
})
これで、 development 環境 (npm start
) ではドラフト記事が確認できて
production 環境 (npm run build
) ではドラフト記事が表示されないようになった。