なにこれ
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は多くのフックポイントを設けているので、今回のよう、やろうと思えば結構いろんなことができます🍅