エンジニアを目指す日常ブログ

日々勉強したことのメモ。独学ですので間違っていたらコメント等で教えてください。

【Gatsby】プロジェクト内に保管したファイルの情報をGraphQLで取得する

はじめに

Gatsbyでブログを書くためには、1ページずつHTMLを書くわけにもいかないので、記事を書いたデータベースからデータを取得してコンポーネントに組み込む必要がある。

開発環境にマークダウン形式の記事を保存し、Gatsbyで取得する方法を確認する。

マークダウンの解析は次回とし、今回はファイルの情報を取得するところまで実施する。

この記事のゴール

  • 開発環境に保存したマークダウン形式の記事の「ファイル名」等のファイル情報を取得する。
    • 開発環境からデータレイヤーに情報を送信する。
    • データレイヤーにGraphQLでアクセスし、情報を取得する。
  • 取得した情報をサイトに表示する。

以下の図の赤字部分が本記事の範囲である。

前回の記事

tomiko0404.hatenablog.com

前提

  • gatsby-starter-blogスターターキットを利用したgatsbyブログを立ち上げ済
  • Vagrantを開発環境として利用
  • Gatsby Cloudで公開済(今回は利用しないので、なくても可)

参考にするサイト

Part 4: Query for Data with GraphQL | Gatsby

今回の流れ

開発環境のcontent/blogフォルダにマークダウン形式の記事を配置し、配置した記事をGraphQLデータレイヤに読み込ませる。

ブログのBlogTutorialコンポーネントから、GraphQL APIを利用してデータレイヤにアクセスしてデータを取得する。

取得したデータをコンポーネントに表示してみる。

マークダウンファイルの準備

content/blogフォルダ配下にブログ記事を用意する。 gatsby-starter-blogスターターキットでは、content/blogフォルダとその配下のサンプル記事(.md)形式が事前に用意されている。

content
└── blog
    ├── ay-page
    │   └── index.md
    ├── hello-world
    │   ├── index.md
    │   └── salty_egg.jpg
    ├── my-second-post
    │   └── index.md
    └── new-beginnings
        └── index.md

マークダウンファイルをGraphQLデータレイヤに読み込ませる

プラグインの利用設定

フォルダのマークダウン記事をGraphQLデータレイヤから読み込むには、gatsby-source-filesystemというプラグインが必要。

データレイヤーに関しては以下の記事を参照。

GatsbyデータレイヤーからgraphQLでデータを取得する - エンジニアを目指す日常ブログ

また、プラグインの使い方は以下の記事を参照。

Gatsbyブログでのプラグイン利用方法/画像の挿入方法 - エンジニアを目指す日常ブログ

gatsby-source-filesystemプラグインがインストールされていない場合は、こちらの記事を参考にnpm installする。

次に、gatsby-config.jspluginの中に以下記載する。(スターターキットを使っているので、既に記載されていた。)

plugins: [
        {
            resolve: `gatsby-source-filesystem`,
            options: {
                path: `${__dirname}/content/blog`,
                name: `blog`,
            },
        },
・・・
],

オプションの意味は以下のようになる。

  • resolveに、プラグイン名を記載
  • ビルド時、pathで指定された${__dirname}/content/blog内のファイルをすべてGraphQLデータレイヤーに追加する。
  • ${__dirname}はNode.jsが保持している特殊な変数で、現在の場所の絶対パスを表す。
  • nameは、特定のフォルダを指定してデータを取得するために、別名として使用する。
// nameオプションの使い方
// このクエリの{eq: "blog"}のところで使う
query {
  allFile(filter: {sourceInstanceName: {eq: "blog"}}) {
    nodes {
      name
    }
  }
}

ちなみに、gatsby-config.jsファイルのpluginの配列要素は、

  • String型でプラグイン名だけ記載
  • オブジェクト型でオプションも含めて記載

の2通りの書き方がある。今回は「オブジェクト型」を利用していることになる。

データレイヤに読み込ませる

gatsby devlopgatsby buildを実行すると、gatsby-config.jsファイルの設定に従ってデータレイヤにデータが読み込まれる。

コンポーネントにクエリを追加する

要求電文の準備

以下の通りgatsby developを実行して、http://localhost:8000/___graphqlにアクセスする。

$ sudo sysctl fs.inotify.max_user_watches=524288
$ gatsby develop --host=0.0.0.0

参考:
Vagrant上でGatsbyブログのひな型を作成した - エンジニアを目指す日常ブログ
gatsby developで出たエラーの対処法 - エンジニアを目指す日常ブログ
GatsbyデータレイヤーからgraphQLでデータを取得する - エンジニアを目指す日常ブログ

以下の要求電文を作り、GraphiQL上で応答を確認する。

query MyQuery {
  allFile {
    nodes {
      name
      sourceInstanceName
    }
  }
}

/content/blog配下のファイル以外も返ってきている。

{
  "data": {
    "allFile": {
      "nodes": [
        {
          "name": "index",
          "sourceInstanceName": "blog"
        },
        // 省略
        {
          "name": "salty_egg",
          "sourceInstanceName": "blog"
        },
        {
          "name": "gatsby-icon",
          "sourceInstanceName": "images"
        },
        {
          "name": "profile-pic",
          "sourceInstanceName": "images"
        },
        {
          "name": "rPOmLGwai2w",
          "sourceInstanceName": "__PROGRAMMATIC__"
        }
      ]
    }
  },
  "extensions": {}
}

クエリ追加と結果確認

要求電文が準備できたので、blog-tutorialコンポーネントに追加する。

以下の記事に記載した通り、graphqlのクエリには以下の特徴があることに注意。

GatsbyデータレイヤーからgraphQLでデータを取得する - エンジニアを目指す日常ブログ

src/pages/blog-tutorial.js

import { graphql } from 'gatsby'
import * as React from 'react'
import MyLayout from '../components/myLayout'

const BlogTutorial = (props) => {
    const {data} = props;
    console.log(data);
    return (
        <MyLayout pageTitle="ブログ一覧">
        </MyLayout>
    )
}

export const query = graphql`
query {
    allFile {
      nodes {
        name
        sourceInstanceName
      }
    }
  }
`
export default BlogTutorial;

※先ほど準備した要求電文から名前(MyQuery)は削除したほうが良い。

実行するとコンソールでdataの中身を確認できる。

data変数の中身
data変数の中身

ファイル名と更新日時を表示してみる

クエリの書き換え

これまでのクエリだと、content/blogフォルダの記事以外のファイルも取得してしまうので、sourceInstanceNameを使ったfilter設定を入れる。

また、このあと表示する更新日時も取得するようにしておく。

export const query = graphql`
query {
  allFile(filter: {sourceInstanceName: {eq: "blog"}}) {
    nodes {
      name
      sourceInstanceName
      modifiedTime
    }
  }
}
`

blog-tutorialコンポーネントで表示

コンポーネントの中身は以下のように記載する。

const BlogTutorial = (props) => {
    const { data } = props;
    console.log(data);
    return (
        <MyLayout pageTitle="ブログ一覧">
            {data.allFile.nodes.map((node) => (
                <>
                    <p>ファイル名:{node.name}</p>
                    <p>更新日時:{node.modifiedTime}</p>
                </>
            ))}
        </MyLayout>
    );
};

表示結果
表示結果

おわりに

ローカルのファイルをデータレイヤに読み込ませるために、gatsby-source-filesystemプラグインの利用方法を覚えた。 また、データレイヤに読み込んだファイル情報をコンポーネントに表示した。

ファイルの情報はこのように取得できるが、マークダウンファイルの中身を上手く扱うには、データレイヤの中で「ファイルノード」を「MDXノード」や「マークダウンRemarkノード」の形式に変換する必要がある。(冒頭の図参照)

次回は「MDXノード」に変換してファイルの中身(ブログ記事)を表示する。

関連記事

つづき