Gatsbyで下書き・予約投稿をする

いつの日かのあなたへ

この記事を読んでいるということは、私は Gatsby の下書き・予約投稿に成功したということだろう。

この機会にそれらの方法をまとめておこうと思う。

といった感じで Gatsby で個人的に納得のできる下書き・予約投稿ができるようになったので、今回はその備忘録です。

Gatsbyとは

モダンで高速でセキュアで美しい静的サイトジェネレーター。

下書き・予約投稿する

このブログの記事は、以下のようなフォーマットで書かれた Markdown で管理しています。

content.md
---
title: first post
date: 2019-01-17
---

This Blog is Built with Gatsby!!!

自分が欲しかった機能は:

  • frontmatter 内の date で日時が指定されている
  • date の日時が gatsby build で実行日時より前であれば記事はビルドされて公開される
  • date の日時が gatsby build の実行日時より後であればビルドされずに公開もされない

というものです。

下書き機能は、記事の日付から公開するどうかを判別できることが最終目的です。この下書き機能が実装できれば、あとは CI で定期的にビルドすることで予約投稿も実現します。

試したこと

GraphQLで日付を比較する

GraphQL Reference

gatsby-node.jscreatePages で実行される GraphQL 内でフィルターを使って、日付の比較を試すも失敗。

文字列ではなく、date: 20190117 のような数値で比較することはできるのですが、あまり得策ではないのでこの手法は却下しました。

nodeのfieldに下書きフラグを追加する

Gatsby の API には createNodeField があり、データ管理をする node にメタデータを追加することができます。これを利用して、公開するかどうか判断するための下書き field を node に追加します。今回はこの方法で下書き機能を実装しました。

gatsby-node.js
exports.onCreateNode = ({ node, actions }) => {
  const { createNodeField } = actions;

  if (node.internal.type !== 'MarkdownRemark') {
    return;
  }

  const nodeDate = new Date(node.frontmatter.date);
  const nowDate = new Date();
  const isDraft = nowDate.getTime() <= nodeDate.getTime();

  createNodeField({
    node,
    name: 'draft',
    value: isDraft,
  });
};

最後に GraphQL のクエリに filter を追加することで、ビルド日時より前の記事だけを公開することができるようになりました。

{
  site {
    siteMetadata {
      title
    }
  }
  allMarkdownRemark(
    filter: { fields: { draft: { eq: false } } } # これを追加する
  ) {
    edges {
      node {
        excerpt
        frontmatter {
          date
          title
        }
      }
    }
  }
}

余談

Gatsby で下書き機能・予約投稿を実装することができました。今回まとめた方法で node の field に下書きフラグを追加するプラグイン gatsby-plugin-draft も公開しました。気になったら使ってみてください。