【GatsbyJS製ブログ】画像の扱い方(gatsby-plugin-image使用例も)

PR

Gatsbyのウリの一つとして「画像の最適化」があります。

上手く画像指定してあげれば自動的にwebp形式で適切なサイズの表示をしてくれます。

しかし、この画像の最適化はGatsbyの鬼門でもあります。特に動的な画像指定はGraphQLも併用しなければいけないのでわかりにくいです。

この記事ではgatsby-plugin-imageを使った画像指定の方法について具体例を示しながら説明していきます。

この記事はこんな人にオススメ
  • Gatsbyで画像の指定方法の基本を知りたい!
  • gatsby-plugin-imageの動的な画像指定ってわかりにくいんだけど…。
目次

インストール

とりあえずgatsby-plugin-image周りのインストールをします。

$ yarn add gatsby-plugin-image gatsby-plugin-sharp gatsby-source-filesystem gatsby-transformer-sharp

gatsby-plugin-sharpは色々なオプションをつけて裏で画像処理をしてくれるやつ、と思ってくれればOKです。gatsby-source-filesystemは静的な画像を扱うときに必要だそうです。同じく、gatsby-transformer-sharpは動的な画像を扱う際に必要だそうです。

クマ

詳しくは公式ドキュメントを参考にしてください。(英語です)

あとはいつも通りgatsby-config.jsのpluginsに書き込むだけです。

module.exports = {
  plugins: [
    …
    `gatsby-plugin-image`,
    `gatsby-plugin-sharp`,
    `gatsby-transformer-sharp`,
    …
  ],
}
クマ

gatsby-plugin-sharpは細かくオプション指定ができるようですが、私は使ったことないです。(英語のドキュメントです)

単純にgatsby-plugin-imageを使って画像の読み込みをしたいだけなら、上記の手順のみで十分でしょう。

StaticImage

StaticImageは静的な画像を扱う際に使うタグです。

静的な画像とは、あらかじめここにこの画像を配置する、というものが決まっている場合の指定方法です。

クマ

なにを当たり前のこと言ってるんだ?画像配置するときには「あらかじめここにこの画像を配置する」って決まってるだろ?

そうなのですが、Gatsbyはその特性上、GraphQLを使いながら前もってブログ記事をビルドする、という操作が必要になってきます。そこでどうしても、ブログ記事の情報を読み取りながらページを作っていく、という操作が必要で、そこで「動的に」画像情報を読み取って配置する、ということをしたりします。

わかりやすい例で言えば「アイキャッチ」ですね。

詳しくは後述しますが、GraphQLを使ってマークダウン(or MDX)のfrontmatterから、「ここにアイキャッチがありますよ」という情報を拾ってきて表示する、というときにはGatsbyImageという動的な画像配置タグを使います。

ですので、逆に「トップページの画像」とか「ヘッダーやフッターに配置する画像」なんかは、記事によって変わることがないので静的な画像を使うStaticImageタグを使えばいい、ということになります。

使い方

使い方は至ってシンプルでsrcプロパティに画像への相対パスを貼ればOKです。StaticImageをgatsby-plugin-imageからインポートするのも忘れないでください。

import { StaticImage } from "gatsby-plugin-image"

…
<StaticImage className = {styles.profileimg}
  src = "../images/toppage/profileimg.JPG"
  alt = "profile img"
  width={400}
></StaticImage>
…

上記のようにクラス名を指定することもできます。altプロパティ(画像が表示されない場合の代替テキスト)は画像表示する際には指定するべきですね。widthプロパティを設定することで、このサイズで画像が読み込まれます。

クマ

私はある程度拡大しても問題ない程度の最小サイズ(width指定)で読み込んでおき、<StaticImage>をdivタグで囲んでそのdivタグのサイズ指定をすることで、レスポンシブとか柔軟に対応しています。

BearFruitのマスコットキャラ「クマ」がLINEスタンプになりました!

プログラマーの心に刺さる、「プログラミングあるある」。毎日使いたくなること間違いなし!

GatsbyImage

GatsbyImageは動的に画像ファイルをとってきて表示するときに使うタグです。

もう少し詳しく説明すると、画像ファイルにchildImageSharp→gatsbyImageDataが追加されるイメージです。GraphQL経由でこのnodeをとってきてgetImageでくるんだものをGatsbyImageで表示する感じです。

クマ

GatsbyImageは若干複雑ですが、上手く扱えるようになると便利です。頑張って理解しましょう!

次のような要領で使っていきます。

import { GatsbyImage, getImage } from "gatsby-plugin-image" //GatsbyImageとgetImageをインポートしておく

const BlogPost = ({data}) =>{ // ※1
  const img = getImage(data.mdx.frontmatter.hero) //GraphQLで拾ってきた画像のnodeをgetImageでくるむ
  
  …
  <GatsbyImage
    image = {img} //先ほどのgetImageでくるんだものをimageプロパティに指定
    alt = "image"
  />
  …

}
…

export const pageQuery = graphql`
query BlogPostBySlug(
    $id: String!
  ) 
    mdx(id: { eq: $id }) {
      id
      body
      frontmatter {
        title
        date(formatString: "MMMM DD, YYYY")
        description
        hero{ //画像ファイルにhildImageSharp→gatsbyImageDataが追加されるイメージ。そのnodeをGraphQLで拾ってくる。
          childImageSharp {
            gatsbyImageData
          }
        }
      }
    }
`

※1 gatsby-node.js(ノードを作ったりページを作ったりするファイル)で使ったテンプレートや、/src/pages/に入っている固定ページ用のJSファイルでは上記の形でGraphQLが扱えます。この形でGraphQLを使うと、この部分のdataにGraphQLの結果が入ってきます

クマ

このあたりのファイル構成は下記の記事も参考にしてみてください。

使用例1「アイキャッチ画像を表示する」

今の例は、実はアイキャッチを表示する方法です。ここではfrontmatterについて説明していきます。

クマ

実際にMDXで書いた記事をご覧いただけたらわかるかと思います。

frontmatter
---
title: テスト投稿
date: "2022-04-03T23:46:37.121Z"
hero: "./eyecatch.JPG"
---

この「—」で囲まれた部分がfrontmatterですね。ここにはその記事の情報を書いていきます。

クマ

実際にはディスクリプションとかもここに書いていきます。

そして、このfrontmatterの情報、GraphQLで拾うことができます。

…
      frontmatter {
        title
        date(formatString: "MMMM DD, YYYY")
        description
        hero{
          childImageSharp {
            gatsbyImageData
          }
        }
      }
…

先ほどの例のここですね。ついでにtitleやdateも引っ張ってきています。この記事とはあまり関係ありませんが、GatsbyImageの周りをそのtitleやdateで飾ってやるとそれっぽくなります。

import { GatsbyImage, getImage } from "gatsby-plugin-image" //GatsbyImageとgetImageをインポートしておく

const BlogPost = ({data}) =>{ // ※1
  const img = getImage(data.mdx.frontmatter.hero) //GraphQLで拾ってきた画像のnodeをgetImageでくるむ
  const post = data.mdx //後々data.mdxはよく使うので、こんな感じでpostという値にしておく。
  
  <header>
    <h1>{post.frontmatter.title}</h1> //h1にtitleを使ったり。
  </header>

  <GatsbyImage
    image = {hero}
    alt = "eyecatch"
  />
  <p>{post.frontmatter.date}</p> //アイキャッチの下に作成日を入れたりできる。

  <MDXRenderer //ここはMDXからブログ記事本体を表示する部分
    frontmatter = {post.frontmatter} //※2
    itemProp = "articleBody"
  >
    {post.body} 
  </MDXRenderer>

  …

}
…

※2 MDXで書いたブログ記事を表示するMDXRendererでは、このように拾ってきたfrontmatterを明示的にfrontmatterプロパティに渡してやらないと上手くfrontmatterの情報をとってこられない場合があります。

アイキャッチ

使用例2「特定のフォルダにある画像を並べる」

下準備として、特定のフォルダにある画像にgatsby-source-filesystemを使ってインスタンス名をつけておきます。そうすることで、GraphQLを使う際にフィルターをかけてここの画像のみ引っ張ってくることができます。

ディレクトリ構成とgatsby-source-filesystemの設定
    …
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `topimages`,
        path: `${__dirname}/src/images/topimages`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    …

nameにインスタンス名、pathにそのインスタンス名をつけるファイルが入ったディレクトリのパスを書きます。

そして、どうやらインスタンス名はgatsby-config.jsの上から順に処理されていくようで、上書きされることはないようです。

ということで、上の画像のように、「images」→「topimages」のようなディレクトリ構成になっている場合は、深いディレクトリからインスタンス名をつけていくといいでしょう。

クマ

このtopimagesディレクトリにある画像をindexに表示してみましょう!

http://localhost:8000/___graphiqlにアクセスすればGraphQLのクエリで上手く画像nodeを取ってこられるか確認できるので活用しましょう。

例えば、index.jsに次のように書き加えると、先ほどの画像が全て表示されます。

…
const BlogIndex = ({ data }) => {
  …
  const topimages = data.topimages.edges 
  const TopImages = topimages.map(({node}) => { //一行上のtopimagesに入っているnodeに対してmapで繰り返し処理
    return (
      <GatsbyImage 
        image = {getImage(node)} //nodeをgetImageでくるんでimageプロパティに渡す。こういう書き方もできる。
        alt = "topimage"
      />
    )
  })
  …
  {TopImages} //画像を表示させたいところに繰り返し処理をしたTopImagesを指定
  …

export const pageQuery = graphql`
  query {
    …
    topimages: allFile(filter: {sourceInstanceName: {eq: "topimages"}}) { //sourceInstanceNameでインスタンス名でフィルター
      edges {
        node {
          name
          childImageSharp {
            gatsbyImageData(
              width: 300 //※3 gatsbyImageDataでは、オプション指定もできる。
            )
          }
        }
      }
    }
  }
`

※3 詳しいオプションについてはこちら。(英語です)

特定ディレクトリの画像表示

まとめ

gatsby-plugin-imageの使い方と具体例を説明しました。

特にGraphQLを使った動的な画像指定は複雑で難しい印象ですが、アイキャッチやサムネ表示など、結構使用頻度が高いです。

MDX内でgatsby-plugin-imageを使う方法については別記事にまとめてあるので、そちらもぜひご覧ください。

Gatsbyを学習している方への私からのオススメ!

私が読んでよかったな、と思うGatsbyの学習をするのにオススメの本を紹介しておきます。

画も多くてとても読みやすく、ステップバイステップでGatsbyJSのサイトを作ることができます!

また、Gatsbyを学習する上で、Reactを同時に学習することもオススメします。

こちらも、まず構成や見た目がとても読みやすい本です。加えてReactに対しての専門的な知識を丁寧に学ぶことができます。ここでReactに対する基礎知識をしっかりしておくと、Gatsbyに対する見方が変わって、Webページをサクサク作ることができるようになります!

あと、色々と調べたのですが、Reactの学習ならUdemyもオススメです。必要な知識を1動画単位で購入できるので、学習に無駄がないです。Reactってあんまり学習できるプログラミングスクールみたいなのがないんですよね…。「React」と検索するだけで大量に動画がでてきます!

あなたへオススメ!
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次