Gatsby-Imageコンポーネントを作る
前提
1ページに複数の画像があり、
全てwebp対応して、
かつ使いまわしたい。
律儀に
まずテンプレを持ってくる。
gatsby-starter-default@0.1.0 develop /Users/goqsystem_77/Desktop/my-gatsby-project
// インストール後
yarn start
さて、お出迎えするのは見慣れた宇宙服のおっさん。
src/components/image.js
をみてみるとこんなコードが書いてあります。
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
const Image = () => {
const data = useStaticQuery(graphql`
query {
placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
`)
if (!data?.placeholderImage?.childImageSharp?.fluid) {
return <div>Picture not found</div>
}
return <Img fluid={data.placeholderImage.childImageSharp.fluid} />
}
export default Image
gatsby-astronaut.png
を検索し、その画像を引っ張ってきているだけですね。
ファイル名を決め打ちしてますから、もちろん使いまわせるはずもありません。
webp対応
まず、上記だとwebpが出力ができてません。対応します。
といってもFragment名を変えるのみです。
...
query {
placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid_withWebp
}
}
}
}
...
これでOKです。
fragment
GatsbyにはFragment
という機能がありまして、任意のフィールドをまとめることができるんですね。
今回だと、GatsbyImageSharpFluid_withWebp
は以下のように展開されます。
fragment GatsbyImageSharpFluid_withWebp on ChildImageSharp {
base64
aspectRatio
src
srcSetWebp
srcWebp
srcSet
sizes
}
このフラグメントですが、どこで定義されたのかというと、gatsby-transformer-sharp
プラグインによって定義されています。
これはプロジェクトにデフォルトでインストールされています。
以下はドキュメントです。
https://www.gatsbyjs.com/plugins/gatsby-image/#fragments
propsで受け取る
webp対応はできました。では使いまわしです。
結論、以下のように書き換えます。
const Image = ({ assetUrl, alt }) => {
const { allImageSharp } = useStaticQuery(graphql`
query {
allImageSharp {
nodes {
fluid(maxWidth: 300) {
originalName
...GatsbyImageSharpFluid_withWebp
}
}
}
}
`)
return <Img fluid={allImageSharp.nodes.find(n => n.fluid.originalName === assetUrl).fluid} alt={alt} />
}
queryにoriginalName
を追加しました。これはファイル名を取得するフィールドです。
propsにassetUrlとaltを設定しました。使用側でデータを渡して、受け取ります。
あとは、findメソッドでoriginalNameとassetUrlが一致するものをフィルタリングし、fluidにアクセスします。
使用側は以下のようにします。
<Image assetUrl='....png' alt='...' />
おじさまだけではつまらないでしょうから、猫を追加しました。
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
<Image assetUrl='gatsby-astronaut.png' alt='astronaut' />
</div>
<div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
<Image assetUrl='neko.jpg' alt='neko' />
</div>
感想
いちいちクエリを作成するのではなく、再利用性があるととても幸せなことに気づきました。