GatsbyJSのImageを設定しよう

01 19, 2019

GatsbyJSのImageを設定しよう

GatsbyJSの初心者殺しのポイントとしてImageの使いにくさがあると思います。(ただし、markdown内は別)
今回はそこをセッティングしていきたいと思います。
GatsbyJSのindex.jsのコードを見てみましょう。

const IndexPage = () => (
  <Layout>
    <SEO title="Home" keywords={[`gatsby`, `application`, `react`]} />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <Link to="/page-2/">Go to page 2</Link>
  </Layout>
)

export default IndexPage

ここの頭の部分でImageコンポーネントを読み込んで<Image />タグで使っているのがわかるかと思います。 それでは/components/image.jsを見てみましょう。

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

const Image = () => (
  <StaticQuery
    query={graphql`
      query {
        placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
          childImageSharp {
            fluid(maxWidth: 300) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    `}
    render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
  />
)
export default Image

HTMLで書くなら

<img src="gatsby-astronaut.png"></img>

と書けば終わりなところをこんなに長く書いています。
しかも、再利用性がないコードで! これがGatsbyJSの初心者殺しポイントです。しかし、これには理由があります。 GatsbyJSのこのやり方は自動で

  • 画像のリサイズ
  • 画像の圧縮
  • Lazyroad という3つの画像最適化作業をしてくれます。
    実際これをやりこむとかなりめんどくさい作業ですが、それを丸投げできるのがGatsbyの良いところです。 /public/static/フォルダを見てみるといくつものサイズの宇宙飛行士のおっさんの画像があることがわかります。 だけどもう少し簡単に書きたい!再利用したいということで書いてみました。 注意:以下のコードは動きません。

    const Image = (props) => (
    <StaticQuery
    query={graphql`
      query {
        placeholderImage: file(relativePath: { eq: ${props.filename} }) {
          childImageSharp {
            fluid(maxWidth: 300) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    `}
    render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
    />
    )

    これで流すと

    Error: BabelPluginRemoveGraphQL: String interpolations are not allowed in graphql fragments.
    Included fragments should be referenced as `...MyModule_foo`.

    StaticQueryというもので書かれておりこれだと動作しません。(GrapgQLについてはあとで詳しく書きます。) ここでの解決策はファイルパスをクエリで全部取得→そしてフィルターをかけて表示させるです。

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

const Image = (props) => ( <StaticQuery query={graphqlquery { images: allFile { edges { node { relativePath name childImageSharp { sizes(maxWidth: 600) { ...GatsbyImageSharpSizes } } } } } }}

render={(data) => {
  const image = data.images.edges.find(n => {
    return n.node.relativePath.includes(props.filename);
  });
  if (!image) { return null; }

  const imageSizes = image.node.childImageSharp.sizes;
  return (
    <Img
      alt={props.alt}
      sizes={imageSizes}
    />
  );
}}

/> ) export default Image

これでindex.jsに
宇宙飛行士 ```

と書けば表示されるはず。/src/images/に適当に画像を追加しましょう。そして表示させてみましょう。

<Image filename="haribo.jpg" alt="haribo" />

注意haribo.jpgはご自身で用意してください。
GatsbyJS Images Sample

お願い

頑張って勉強しながら書いています。間違いなどがあればご指摘いただけたらうれしいです。


コリ

コリといいます。奈良県でサラリーマンをしています。GatsbyJSでサイトを作るのが趣味です。