thumbnail

なにこれ

GatsbyでWebサイトを作るときに、ブログや職種紹介など2種類以上のマークダウンファイルを管理する場合があると思います。通常だとMarkdownRemarkNodeのfileAbsolutePathでしか両者のマークダウンファイルを見分ける術がありませんが、ここではもっとスマートなやり方を紹介します。簡単に言うとFileNodeのsourceInstanceNameをMarkdownRemarkNodeに引き継ぐことにより、GraphQLのfilterで簡単に区別できるという方法です。

実装方法

Step1. マークダウンファイルのFleNodeでsourceInstanceNameを定義

マークダウンファイルの読み込み設定はgatsby-config.jsで以下のようにします。 nameを付けることでマークダウンファイルのFileNodeにおいてsourceInstanceNameが設定できます。

gatsby-config.js
module.exports = {
  /* (中略) */

  plugins: [
    /* (中略) */

    {
      resolve: 'gatsby-source-filesystem',
      options: {
        // オプションでname(FileNodeにおけるsourceInstanceName)を指定
        name: 'posts',
        path: `${__dirname}/content/posts`,
      },
    },
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        // オプションでname(FileNodeにおけるsourceInstanceName)を指定
        name: 'jobs',
        path: `${__dirname}/content/jobs`,
      },
    },
    'gatsby-transformer-remark',

    /* (中略) */
  ],

  /* (中略) */
};

Step2. FileNodeのnameをMarkdownFileNodeに引継ぐ

何もしないとFileNodeのsourceInstanceNameはMarkdownRemarkNodeに引き継がれません。 そのためgatsby-node.jsで引継ぎ処理を実装します。

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

  // MarkdownRemarkNodeの場合のみ処処
  if (node && node.internal && node.internal.type === 'MarkdownRemark') {

    // 親のFileNodeを取得して
    const parent = getNode(node.parent)

    // gatsby-config.jsで設定したFileNodeのsourceInstanceNameを
    // MarkdownRemarkのフィールドに引き継ぐ
    // 名前はMarkdownRemarkの他プロパティとかぶらないようにcollectionとしている
    createNodeField({
      node,
      name: 'collection',
      value: parent.sourceInstanceName,
    })
  }
};

Step3. GraphQLでnameをもとにマークダウンを区別

GraphQLではcollectionフィールドで、それぞれを区別します。

query {
  allMarkdownRemark(
    # collectionにて記事のNodeのみ抽出
    filter: { fields: { collection : { eq: "posts" } } }
  ) {
    edges {
      node {
        # (中略)
      }
    }
  }
}

まとめ

簡単ですがGatsbyで良く困る事例の1つを紹介しました。 Gatsbyは多くのフックポイントを設けているので、今回のよう、やろうと思えば結構いろんなことができます🍅

参考