Gatsby

Gatsbyでサムネイルを表示する方法についてまとめました。

いつもご利用ありがとうございます。このブログは、広告費によって運営されています。

⇨ React 記事の目次はこちら

Gatsby でマークダウンで記事を書く際に、サムネイルを設定しようとしたら思いの他時間がかかったので、記事にしました。node-config でサムネイルの graphql に対して相対パスの指定をする必要がありました。

前提

スターターで、以下のものを使用しています。

Gatsby Starter Blog

つまり、以下のようなプラグインはすでに入っている前提で進めていきます。

gatsby-plugin-sharp gatsby-source-filesystem gatsby-transformer-sharp

最後に表示するときに使う gatsby-image をインストールします。

npm install --save gatsby-image

マークダウンと同じディレクトリに画像を設置

今回は、

/content/blog/new-beginnings/index.md
/content/blog/new-beginnings/top.jpg

このように画像と md ファイルが設置されています。

md ファイルにサムネイルの項目を追加する

thumbnail を相対パスで指定します。今回は同じディレクトリにあるので、ファイル名だけです。

---
title: New Beginnings
date: "2015-05-28T22:40:32.169Z"
description: 最初にあるmdファイルを編集してます
thumbnail: "top.jpg"
---

gatsby-node.js を編集する

/gatsby-node.js の下の方に、

Frontmatter に関する定義がされている場所を以下のように変更します。

    type Frontmatter {
      title: String
      description: String
      date: Date @dateformat
      thumbnail: File @fileByRelativePath
    }

thumbnail が File であることを定義します。

そうすることによって、後述するファイル用(sharp)graphql が使えるようになります。

これを書かないと、childImageSharp を使おうとするとエラーになります。

ちなみに File ではなく、String を指定すると以下のようなエラーになります。

There was an error in your GraphQL query:

      Field "thumbnail" must not have a selection since type "String" has no subfields.

      This can happen if you e.g. accidentally added { } to the field "thumbnail". If you didn't expect "thumbnail" to be of type "String" make sure that your input source
and/or plugin is correct.

そして、@fileByRelativePath によって、画像のファイルの位置が相対パスであることを定義します。

これを書かないと、相対パスでちゃんと画像の位置を指定しても、childImageSharpがnullになります。

僕はこれを知るために3時間かかったので記事にしています(汗)

一覧の graphQL

thumbnail の項目を追加

export const pageQuery = graphql`
  query {
    site {
      siteMetadata {
        title
      }
    }
    allMarkdownRemark(
      sort: { fields: [frontmatter___date], order: DESC }
      filter: { fileAbsolutePath: { regex: "/(blog)/" } }
    ) {
      nodes {
        excerpt
        fields {
          slug
        }
        frontmatter {
          date(formatString: "MMMM DD, YYYY")
          title
          description
          thumbnail {
            childImageSharp {
              fluid(maxWidth: 1280) {
                ...GatsbyImageSharpFluid
              }
            }
          }
        }
      }
    }
  }
`;

表示の書き方

graphQL で取得した画像を、Image の fluid(gatsby-image)に指定する。

画像を設定しない記事もあるかもしれないので、一応 optional をつけてます。

import Image from "gatsby-image";

const BlogIndex = ({ data, location }) => {
  const siteTitle = data.site.siteMetadata?.title || `Title`;
  const posts = data.allMarkdownRemark.nodes;
  return (
    <div>
      {posts.map((post) => {
        const title = post.frontmatter.title || post.fields.slug;
        const thumbnail = post.frontmatter.thumbnail?.childImageSharp.fluid;
        return (
          <div>
            <Image fluid={thumbnail} alt="ポッポテニス画像" />
            <Link to={post.fields.slug} itemProp="url">
              <span itemProp="headline">{title}</span>
            </Link>
          </div>
        );
      })}
    </div>
  );
};

export default BlogIndex;

まとめ

以上です。

スターターがアップデートをしたのか分かりませんが、gatsby-node のところ、情報がなくて結構ハマりました。

誰かの参考になれば幸いです。

それでは!!!

質問、誤記などあれば Twitter などでご指摘よろしくおねがいします!

人気記事

PHP7.4 + Laravel6 のプロジェクトを AWS EC2 にデプロイする

関連記事

【ReactNative+CloudVision】「怒り顔採点アプリ」を作った