Gatsbyで画像を取り扱う
2020年06月22日
Gatsby での基本的な画像の取り扱いについてメモ!
必要なプラグイン
GatsbyのGraphQLクエリとシームレスに動作するように特別に設計されたReactコンポーネント。
サイトの画像読み込みを簡単かつ完全に最適化する。
サイトの画像読み込みを簡単かつ完全に最適化する。
画像処理ライブラリSharpの機能を提供する。
画像処理ライブラリSharpでサポートされている画像タイプからImageSharpノードを作成する。
ローカルファイルからFileノードを作成する。
GraphQL で取得する
ファイル名はprofile-pic.jpg
であり fluid(伸縮)し最大幅は 400px, 対応ブラウザでは WebP 画像で表示して最適化する場合、このような GraphQL クエリを作成する。
GraphQLクエリ
query {file(relativePath: { eq: "profile-pic.jpg" }) {childImageSharp {fluid(maxWidth: 400) {base64aspectRatiosrcsrcSetsrcWebpsrcSetWebpsizes}}}}
出力結果を見る
fragments を使う
先程は以下のフィールドを指定したが、毎回指定するのは大変でミスもありそうだ。共通化したい。。
- base64
- aspectRatio
- src
- srcSet
- srcWebp
- srcSetWebp
- sizes
そこでfragmentsというものがあり簡略化して書ける!
GraphQLクエリ
query {file(relativePath: { eq: "profile-pic.jpg" }) {childImageSharp {fluid(maxWidth: 400) {...GatsbyImageSharpFluid_withWebp}}}}
出力結果を見る
gatsby-image の fragments はgatsby-transformer-sharp/src/fragments.jsで確認ができます!
このように fragments はプラグインで定義されていたり、自分で定義することも可能です。
gatsby-image で画像を表示する
たとえばsrc/pages/index.js
で表示する例を見てみましょう。
src/pages/index.js
import React from 'react';import { graphql } from 'gatsby';import Image from 'gatsby-image';export default ({ data }) => <Image fluid={data.file.childImageSharp.fluid} />;export const query = graphql`query {file(relativePath: { eq: "profile-pic.jpg" }) {childImageSharp {fluid(maxWidth: 400) {...GatsbyImageSharpFluid_withWebp}}}}`;
まず以下の部分で、GraphQL クエリをexport
しています。
変数名query
はなんでも構いません。
export const query = graphql`query {file(relativePath: { eq: "profile-pic.jpg" }) {childImageSharp {fluid(maxWidth: 400) {...GatsbyImageSharpFluid_withWebp}}}}`;
export
したクエリの結果は props で受け取ることができます。
クエリの出力結果は以下でdata
というプロパティに値が入っているので分割代入で受け取っています。
GraphQL出力結果
{"data": {"file": {"childImageSharp": {"fluid": {"base64": "data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAIDBAX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgD/2gAMAwEAAhADEAAAAetCeAdrCxfxiiwS/wD/xAAcEAACAgIDAAAAAAAAAAAAAAABAgADERIEEyL/2gAIAQEAAQUCJAD+AMsGlr7q3K1lpPXaTmpQV//EABURAQEAAAAAAAAAAAAAAAAAABBB/9oACAEDAQE/ASn/xAAYEQACAwAAAAAAAAAAAAAAAAAAARARMf/aAAgBAgEBPwEoWR//xAAbEAADAAIDAAAAAAAAAAAAAAAAAREQMQISUf/aAAgBAQAGPwKMpfTVOrnFk3hY/8QAGxABAAMAAwEAAAAAAAAAAAAAAQARMSFRgUH/2gAIAQEAAT8h9URFuveYynBcWOHyLsnFgsJxNIJpLx2S9vc//9oADAMBAAIAAwAAABCj0D//xAAYEQADAQEAAAAAAAAAAAAAAAAAAREQMf/aAAgBAwEBPxBRdKPH/8QAGBEAAgMAAAAAAAAAAAAAAAAAATEAEBH/2gAIAQIBAT8QwlXy5//EAB0QAQEBAAICAwAAAAAAAAAAAAERACExQWFRcYH/2gAIAQEAAT8Q9Sgc6KQvBCL+YV4DsZFEAr0q+O9YxLboHUcFKQTgvrnKpH5NUGoW+c/FpHH0b//Z","aspectRatio": 1,"src": "/static/0c1679c2f769226599c1b61833c382b9/2244e/profile-pic.jpg","srcSet": "/static/0c1679c2f769226599c1b61833c382b9/86e11/profile-pic.jpg 100w,\n/static/0c1679c2f769226599c1b61833c382b9/f836f/profile-pic.jpg 200w,\n/static/0c1679c2f769226599c1b61833c382b9/2244e/profile-pic.jpg 400w","srcWebp": "/static/0c1679c2f769226599c1b61833c382b9/1f5c5/profile-pic.webp","srcSetWebp": "/static/0c1679c2f769226599c1b61833c382b9/d1f52/profile-pic.webp 100w,\n/static/0c1679c2f769226599c1b61833c382b9/61e93/profile-pic.webp 200w,\n/static/0c1679c2f769226599c1b61833c382b9/1f5c5/profile-pic.webp 400w","sizes": "(max-width: 400px) 100vw, 400px"}}}}}
そのなかのfluid
。つまりこのようなオブジェクトを
fluid
{"base64": "data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAIDBAX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgD/2gAMAwEAAhADEAAAAetCeAdrCxfxiiwS/wD/xAAcEAACAgIDAAAAAAAAAAAAAAABAgADERIEEyL/2gAIAQEAAQUCJAD+AMsGlr7q3K1lpPXaTmpQV//EABURAQEAAAAAAAAAAAAAAAAAABBB/9oACAEDAQE/ASn/xAAYEQACAwAAAAAAAAAAAAAAAAAAARARMf/aAAgBAgEBPwEoWR//xAAbEAADAAIDAAAAAAAAAAAAAAAAAREQMQISUf/aAAgBAQAGPwKMpfTVOrnFk3hY/8QAGxABAAMAAwEAAAAAAAAAAAAAAQARMSFRgUH/2gAIAQEAAT8h9URFuveYynBcWOHyLsnFgsJxNIJpLx2S9vc//9oADAMBAAIAAwAAABCj0D//xAAYEQADAQEAAAAAAAAAAAAAAAAAAREQMf/aAAgBAwEBPxBRdKPH/8QAGBEAAgMAAAAAAAAAAAAAAAAAATEAEBH/2gAIAQIBAT8QwlXy5//EAB0QAQEBAAICAwAAAAAAAAAAAAERACExQWFRcYH/2gAIAQEAAT8Q9Sgc6KQvBCL+YV4DsZFEAr0q+O9YxLboHUcFKQTgvrnKpH5NUGoW+c/FpHH0b//Z","aspectRatio": 1,"src": "/static/0c1679c2f769226599c1b61833c382b9/2244e/profile-pic.jpg","srcSet": "/static/0c1679c2f769226599c1b61833c382b9/86e11/profile-pic.jpg 100w,\n/static/0c1679c2f769226599c1b61833c382b9/f836f/profile-pic.jpg 200w,\n/static/0c1679c2f769226599c1b61833c382b9/2244e/profile-pic.jpg 400w","srcWebp": "/static/0c1679c2f769226599c1b61833c382b9/1f5c5/profile-pic.webp","srcSetWebp": "/static/0c1679c2f769226599c1b61833c382b9/d1f52/profile-pic.webp 100w,\n/static/0c1679c2f769226599c1b61833c382b9/61e93/profile-pic.webp 200w,\n/static/0c1679c2f769226599c1b61833c382b9/1f5c5/profile-pic.webp 400w","sizes": "(max-width: 400px) 100vw, 400px"}
gatsby-image
からimport
したコンポーネントに渡すことで最適化した画像を表示します。
import Image from 'gatsby-image';export default ({ data }) => <Image fluid={data.file.childImageSharp.fluid} />;