Gatsbyでサイトを作成しようとする前にGatsbyでは画像の設定はどのように行うのだろうかという疑問がある方も多いかと思います。Gatsbyの公式ドキュメントには画像について記載はされていますが少し難しい箇所もあるので本文書では入門者でもわかりやすいように丁寧に説明を行っていきます。

Gatsbyでは大きく分けて画像の設定には4つの方法があります。本文書では4つの方法について説明を行っているので、順番に読み進めていくGatsbyの画像設定の理解も深まるかと思います。一番シンプルな方法は3番目に記述する/staticディレクトリに画像を保存する方法です。最も重要なのが最後のGatsby-imageプラグインを利用した方法です。

ディレクトリからのファイルのimport

まず最初にimagesディレクトリに保存した画像ファイルをブラウザに表示させる方法を確認します。

srcディレクトリの下にimagesディレクトリを作成し任意の画像ファイルを保存してください。ここではtest.jpgという名前の画像ファイルを保存しています。

gatsby developコマンドを実行している場合、imagesディレクトリに画像ファイルを保存すると同時に保存したファイルが認識されビルドが行われます。
fukidashi

src/pagesディレクトリに保存されたindex.js上に画像の設定を行います。index.js上ではこれまでのHTMLの知識の延長で相対パスを設定すれば問題なく画像が表示されるだろうと考えるのが一般的かと思います。


<img src="../images/test.jpg" alt="test" />

しかし残念ながら上記の方法では画像を表示させることはできません。

imagesディレクトリに保存したファイルを表示させるためにはファイルをimportする必要があります。


import React from "react"
import Layout from "../components/layout"
import { graphql, Link } from "gatsby"
import Test from "../images/test.jpg" //追加

import後にTestをsrcに指定するとブラウザ上に画像を表示させることができます。


<h1>Gatsby Blog Site</h1>
<img src={ Test } alt="test" />
ブラウザで表示されているファイルのパスを確認すると/image/test.jpgではなく/static/test-3a3ff03feb56529a3047867d284e8040.jpgと表示されます。
fukidashi

importをするなど一見手間がかかりますが、タイプミスや間違ってファイルを削除した場合などはビルド時にエラーが表示されるので事前にエラーで設定ミスを把握することできます。またファイル名には、ハッシュが付けられるためファイル名が同じでファイルの内容に変更があった場合にキャッシュによりブラウザ上の画像が更新されないということもありません。

GraphQLによる画像の取得

Gatsbyをインストール後、プラグインgatsby-source-filesystemをインストールしてGraphiQLでqueryを実行するとローカルファイルの情報を取得することができます。

画像ファイルもローカルファイルの一種なので、GraphiQLのqueryを実行するとimagesディレクトリに保存したファイルの情報を取得することができます。

GraphiQLのqueryで画像ファイルパス取得
GraphiQLのqueryで画像ファイルパス取得

GraphiQLで取得したPublicURLを下記のようにsrcに指定しても画像をブラウザ上に表示することができます。


<img
  src="/static/3a3ff03feb56529a3047867d284e8040/test.jpg"
  alt="test"
/&gt;

GraphiQLの結果から確認したpublicURLを直接srcに指定することもできますがGraphQLのqueryの実行結果をそのまま利用することもできます。ファイルパスをGraphQLを使って取得したことがない人にとっては少し驚くかもしれませんがこの後説明するgatsby-imageもGraphQLを利用するのこの方法に慣れておく必要があります。

ページコンポーネントの場合は下記のようにPage Queryで実行します。


export const query = graphql`
  {
    file(name: { eq: "test" }) {
      publicURL
    }
  }
`

実行結果はpropsのdataの中に入ってくるので、dataを展開することでpublicURLを取り出すことができます。


import { graphql } from "gatsby"
// 略
export default function Home({ data }) {
// 略
<img src={data.file.publicURL} alt="test" />

コンポーネントの場合はstaticQueryを使って実行します。


import { useStaticQuery, graphql, Link } from "gatsby"

const Header = () => {
  const data = useStaticQuery(
    graphql`
      {
        file(name: { eq: "test" }) {
          publicURL
        }
      }
    `
  )
// 略
<img src={data.file.publicURL} alt="test" />

これまでの経験であればローカルの画像ファイルを表示するためにqueryを実行するということはなかったかもしれませんが、GatsbyではGraphQLのqueryの結果を利用して画像を設定できます。

staticディレクトリへのファイルの保存

staticディレクトリを利用する方法が一番シンプルに画像の設定を行うことができます。

プロジェクトディレクトリの直下にstaticというディレクトリがあります。その中に画像ファイルを保存してください。staticディレクトリに画像ファイルを保存するとpublicディレクトリに画像ファイルが自動でコピーされます。ここではphoto.pngという画像ファイルを利用しています。

この場合はHTMLで通常利用する形に似ていますが、staticの下に保存したのでstatic/photo.pngとsrcに指定するのではなくpublicフォルダに保存されているphoto.pngと指定するだけで画像が表示されます。


<img src="/photo.png" alt="this is a test" />
altにphotoというキーワードを入力するとgatsby developのコンソールメッセージにwarning Redundant alt attribute. Screen-readers already announce `img` tags as an image. You don’t need to use the words `image`, `photo,` or `picture` (or any
specified custom words) in the alt propと表示されます。imgタグを指定している時点で画像や写真なのでimageやphotoやpictureといった単語はaltに使用する必要がないといった内容です。
fukidashi

ここまでの説明でGatsbyでは3つの方法を使って画像を表示できることがわかりました。次はプラグインを利用して画像を利用する方法を確認していきます。

Gatsby-imageプラグインを利用した画像の設定

ここまでの説明でブラウザ上に画像が表示されたのでGatsbyでの画像の設定はこれで大丈夫かと思うかもしれませんが、Gatsbyには画像の最適化とパフォーマンスを向上させるための重要なプラグインがあります。プラグインを利用することで手間のかかる画像の最適化の作業を自動化することができます。

Gatsby-imageというプラグインを利用するためにはGatsby-imageを含め、3つのプラグインをインストールする必要があります。


% npm install gatsby-transformer-sharp gatsby-plugin-sharp gatsby-image

インストール後にプラグインを利用するためにgatsy-config.jsファイルを更新する必要があります。他のプラグインの情報を記述されているので削除しないように注意しながら追加を行ってください。

gatsy-source-filesystemプラグラインで画像の保存しているフォルダを指定しておきます。ここではimagesを指定しており、srcディレクトリ下にimagesディレクトリが必要です。


  plugins: [
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
3つのインストールしたプラグインのうちgatsby-imageはgatsy-config.jsファイルで設定する必要はありません。
fukidashi

設定完了後、gatsby-developコマンドを再実行します。http://localhost:8000/___graphqlにアクセスしていGraphiQL起動します。GraphiQLを確認すると新たにallimageSharpとimageSharpが追加されていることを確認することができます。表示されない場合はgatsby-config.jsファイルを確認してgatsby-developコマンドを再実行してください。

GraphiQLに追加されていることを確認
GraphiQLに追加されていることを確認

allImageSharpを利用してimagesに保存されているtest.jpgの情報が取得できるか確認を行います。他にもさまざまな情報が取得できますが、ここではsrcとオリジナルのファイル名を取得しています。


query MyQuery {
  allImageSharp {
    nodes {
      original {
        src
      }
      sizes {
        originalName
      }
    }
  }
}

上記のqueryを実行するとハッシュの入ったファイル名とオリジナルのファイル名を取得することができます。

画像の情報を取得
画像の情報を取得

allImageSharpでも画像の情報を取得することができますが、allFileやfileでもファイル情報を取得することができます。ここからはfileを利用して画像の設定に必要なファイル情報を取得します。


query {
  file(relativePath: {eq: "test.jpg"}) {
    id
    childImageSharp {
      fixed {
        src
        srcSet
        originalName
      }
    }
  }
}

queryを実行する際はrelativePathでtest.jpgを指定しています。またsrcSetでは3つの結果が表示されます。

GraphiQLを使ってfileのquery実行
GraphiQLを使ってfileのquery実行

Gatsby-imageでは2つの画像のタイプをサポートしており、fixed, fluidでquery時に指定することができます(上記のqueryではfixedを指定)。fixedは固定の横幅と高さを指定することができます。fluidはブラウザのサイズに合わせて画像のサイズが変わります。この後どのような違いがあるのか実際に設定を行い比較していきます。

gatsby-imageの動作確認

実際にコードを利用して画像の情報を取得しブラウザに表示させます。下記が実行のコードです。設定内容の詳細は下記で説明を行います。


import Img from "gatsby-image"
// 略
const data = useStaticQuery(
graphql`
    {
    testFixed: file(relativePath: { eq: "test.jpg" }) {
        childImageSharp {
        fixed(width: 300) {
            ...GatsbyImageSharpFixed
        }
        }
    }
    testFluid: file(relativePath: { eq: "test.jpg" }) {
        childImageSharp {
        fluid(maxWidth: 300) {
            ...GatsbyImageSharpFluid
        }
        }
    }
    }
`
)
//略
<Img fixed={data.testFixed.childImageSharp.fixed} alt="test fixed" />
<Img fluid={data.testFluid.childImageSharp.fluid} alt="test fluid" />

gatsby-imageを利用するためにはgatsby-imageをimportする必要があります。

fluidとfixedを比較するために2つのqueryを実行しているのでqueryにtestFixedとtestFluidと任意の名前をつけています。データを取り出す時に利用することができます。1つのコンポーネントから複数の画像を取得する際は任意の名前をつける必要があります。

test.jsは/src/imagesの直下に保存されており、relativePathではimagesディレクトリからのファイルのパスを設定しています。今回はimagesの下に保存されているtest.jpgを指定します。widthで固定幅の300を指定しています。…GastbyImageSharpFixedはFragmentと呼ばれいくつかの設定値があります。

Fragmentを設定することによってGraphQLで実行するQueryの取得内容を毎回設定することなく再利用することができます。
fukidashi

HTML側のImgタグの中ではpropsのfixedにはfixedから取得したデータを指定しpropsのfluidにはfluidから取得データを指定します。ここでquery時につけた名前(testFixed, testFluid)を利用しています。

ブラウザで確認するとfixedとfluidの違いが簡単にわかります。上がfixedなので画像のサイズが固定されていることがわかります。fluidの場合はブラウザのサイズに合わせて画像のサイズが広がっていることがわかります。

fixedとfluidの比較
fixedとfluidの比較

ブラウザの幅を狭めていくと上側のfixedのサイズは変わりませんが、下側のfluidのサイズがブラウザ幅に合わせて変わります。

fixedとfluidの比較
fixedとfluidの比較

デベロッパーツールで確認するとimgのsrc属性が一つ設定されているだけではなくsource srcsetなどさまざまな設定が行われておりブラウザのスクリーン要件にあった画像を読み込むことができるようになっています。このようにgatsby-imageを利用すると画像の最適化の処理が自動で行われます。

デベロッパーツールでの確認
デベロッパーツールでの確認

gatsby-imageについては本文書では画面に画像を表示させることまでは確認しましたが、Fragmentやその他のpropsについての説明は行っていません。本文書を読み終えることでGatsby-imageの使用方法の基本が理解できたと思いますので、Fragmentやその他の設定についてはぜひドキュメントを参考に動作確認を行ってみてください。