Gatsbyでローカルの画像を使う方法

Gatsbyのプロジェクトでローカルの画像を表示している箇所のコードについて、公式ドキュメントを読みました。そのメモを残しておきます。

まずはサイトの左上にあるホームページに戻るリンクの画像の取得をどうやっていたか確認します。

ホームページに戻るためのリンク

この画像は、src\images\over40webshop.png として格納されていて、Reactのコードは次のようになっています。

import React from 'react';
import Img from 'gatsby-image';
import { useStaticQuery, graphql } from 'gatsby';

export const Logo = () => {
  const data = useStaticQuery(graphql`
    {
      file(relativePath: { eq: "over40webshop.png" }) {
        childImageSharp {
          fixed(width: 160) {
            ...GatsbyImageSharpFixed_withWebp
          }
        }
      }
    }
  `);

  return <Img fixed={data.file.childImageSharp.fixed} />;
};

なかほどに”over40webshop.png”というファイル名が指定されていて、相対パスのようです。まずは、useStaticQuery がなにか調べてみました。

useStaticQuery

Gatsbyのドキュメントを見ると次のように書いています。

  • useStaticQuery StaticQuery Reactフックバージョンである(Gatsby v2.1.0 で導入された)
  • Reactフックとは、React 16.8で追加されたもので、state などの React の機能をクラスを書かずに使えるにしたもの
  • StaticQuery を使った Header コンポーネントの例が示されています。
Copysrc/components/header.js: copy code to clipboard
import React from "react"
import { StaticQuery, graphql } from "gatsby"
export default function Header() {
  return (
    <StaticQuery
      query={graphql`
        query HeadingQuery {
          site {
            siteMetadata {
              title
            }
          }
        }
      `}
      render={data => (
        <header>
          <h1>{data.site.siteMetadata.title}</h1>
        </header>
      )}
    />
  )
}
  • StaticQuery を使うことによって Header コンポーネントは上位コンポーネント(例えばLayout)から props でデータを渡されなくてもデータを利用できるようになります。
  • StaticQuery は2つの引数を持ちます。一つはクエリpropsで、もうひとつレンダーpropsです。
  • useStaticQuery StaticQuery Reactフックバージョンなので次のような感じで、コンポーネントでデータを取得できるということですね。
import React from 'react';
import Img from 'gatsby-image';
import { useStaticQuery, graphql } from 'gatsby';

export const Logo = () => {
  const data = useStaticQuery(graphql`
    {
      // クエリ
    }
  `);

  return <Xxx {dataを用いたレンダリングのコード} />;
};

画像をファイルシステムからロードする方法

これは公式ドキュメントでは”Importing Assets Directly into Files“で説明されています。画像やフォント、ファイルをGatsbyサイトにインポートする方法は2種類あるとのことです。

  1. webpackでアセットをインポート
  2. gatsby-source-filesystemによりGraphQLのFileをクエリ

webpackでアセットをインポート

これは次のような方法です。プロジェクトをビルドすると、Webpackが画像をpublicフォルダに正しく移動し、正しいパスを提供します。0,000バイト未満の画像をインポートすると、パスではなくデータURIが返されます(ウェブページにインラインにデータが埋め込まれる) 。

import React from "react"
import logo from "./logo.png" // Tell webpack this JS file uses this image
console.log(logo) // /logo.84287d09.png
function Header() {
  // Import result is the URL of your image
  return <img src={logo} alt="Logo" />
}
export default Header

gatsby-source-filesystemによりGraphQLのFileをクエリ

  • データ 層でGraphQL を使用してクエリすることで ファイルをインポートすることもできます。
  • File ノードの publicURL フィールドに問い合わせると、JavaScript コンポーネント、ページ、テンプレートで使用できる URL が提供されます。
  • 次のコードでは、拡張子がpdfである全てのファイルを参照することができます。
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Layout from "../components/layout"
const DownloadsPage = () => {
  const data = useStaticQuery(graphql`
    {
      allFile(filter: { extension: { eq: "pdf" } }) {
        edges {
          node {
            publicURL
            name
          }
        }
      }
    }
  `)
  return (
    <Layout>
      <h1>All PDF Downloads</h1>
      <ul>
        {data.allFile.edges.map((file, index) => {
          return (
            <li key={`pdf-${index}`}>
              <a href={file.node.publicURL} download>
                {file.node.name}
              </a>
            </li>
          )
        })}
      </ul>
    </Layout>
  )
}
export default DownloadsPage