初心者による初心者のためのGatsbyJS覚書3(画像の最適化編)


この記事について

この記事はGatsbyJS初心者の新卒2年目が作成しています。
参考資料として書籍を使用していますが、筆者がビギナークラスのため読んでいて「?」となる部分や間違っている箇所もあるかと思います。
参考までに、そして間違えている箇所がありましたらご連絡いただけると嬉しいです。

Chapter2:画像の最適化の備忘録メモ

注意
参考資料である「Webサイト高速化のための静的サイトジェネレーター活用入門」では
まだGatsby v2の手法が記載されているが、今回環境構築をした際、最新版のv3で作っているので
参考書通りとはならなかったが、付属されているv3用のダウンロード資料をもとに取り組んでみた。

「Gatsby v2」と「Gatsby v3」の違いについて

この画像の最適化編で大きく影響してくるのはズバリ
「インストールするプラグインとそのルールの違い」である。
v2までは「gatsby-image」というプラグインをインストールしていたが、
v3からは新しく「gatsby-plugin-image」というプラグインが導入されている。

ざっくり説明するとgatsby-imageで必要だった画像最適化までの手順が
gatsby-plugin-imageだと大幅に削減されるよって話らしい。
gatsby-plugin-imageではStaticImageとGatsbyImageの2つが使用でき、
StaticImageはGraphQLを使わずに最適化した画像を引っ張ってこれるため使い勝手が◎

ひとまず必要なプラグインたちをインストールしておく。

npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-transformer-sharp gatsby-source-filesystem

gatsby-transformer-sharpは後にダイナミックイメージ(GatsbyImage)を使用する場合に必要
gatsby-source-filesystemはStaticのImageを使っている場合必要

あとは使いたいファイルにインポートして使うのみ。

import { StaticImage, GatsbyImage } from "gatsby-plugin-image"

バージョンの違いで解説を使いつつも手間取った部分

gatsby-imageを使用している場合、src/配下のimageを取得しようとするとクエリを作成する必要がある。
なので参考資料の解説も「クエリを使用していること」を前提に進んでいくわけだが、
やはり諸々使い勝手が違いすぎで初心者大混乱。笑

GraphQLの構造も自分が見つけたいデータがなかなか見つからず大冒険の果てにデータを探し当て
達成感とともにハッと気がつく。「あれ、そういえばStaticImage使えば早いのでは、」と。
そして解説のPDFにもすこし進むとそのことが記載されている。。。(早く言ってよ心の中で叫ぶ。

結局クエリを使用しない方法を取ったので日の目をみることがはなかったが
頭を悩ませた記念にデータ構造だけ写真に収めておくことにする。
悩んだのはFULL WIDTHなどをもつlayoutのチェックボックスがなかなか見つからなかったため。
childImageSharpが同階層に2つあるのに気がつけなかったのが運の尽き、、、
GraphQLでなんか欲しいデータ取れないな、、、と思ったら
「その階層ではないのでは?と広い視野でパトロールをしましょう。」が今回の教訓。

そのlayoutでの選択肢ってどういう意味?となったのでそれについての参考はこちら

それをクエリでこんな感じで各画像ごとにエイリアスをつけて取得。

export const query = graphql`
  query {
     hero: file(relativePath: { eq: "hero.jpg" }) {
       childImageSharp {
         gatsbyImageData(layout: FULL_WIDTH)
       }
     }
     fruit: file(relativePath: { eq: "fruit.jpg" }) {
       childImageSharp {
         gatsbyImageData(width: 320, layout: CONSTRAINED)
       }
     }
  }
`

画像を出力する部分にはこのように記述。

<GatsbyImage
  image={data.hero.childImageSharp.gatsbyImageData}
  alt=""
  style={{ height: "100%" }}
/>

<GatsbyImage
 image={data.grain.childImageSharp.gatsbyImageData}
 alt=""
/>

StaticImageで手っ取り早く画像最適化

StaticImageならクエリいらずでGatsbyImageと同等の画像の最適化ができるらしい。最高。
GatsbyImageを使用したときに指定していたlayoutの設定もこのように書けば指定できる。
StaticImageしか使用しないのであればgraphqlGatsbyImageのインポートは不要。

//例1
<StaticImage
  src="../images/hero.jpg"
  alt=""
  layout="fullWidth"
/>
//例2
<StaticImage
  src="../images/fruit.jpg"
  alt=""
  layout="constrained"
  style={{ width :"320px"}}
/>

プラグインを使用して最適化した画像のスタイルを整える

 StaticImageGatsbyImageを使用して画像を最適化してみると
さっきまで整っていた見た目に変な余白、ズレ、見えなくなるなどの事象が発生。
「なんだこれ?」と思っていたがどうやらプラグインで最適化すると今まで効いていたCSSが無効になるとか。
解説によると「画像の読み込み中もスペースを確保するためにgatsby-image-wrapperが画像の縦横比にあわせたボックスを構成してくれっちゃってる」らしい。

解決方法はこんなかんじ。

<StaticImage
  src="../images/hero.jpg"
  alt=""
  layout="fullWidth"
  style={{ height :"100%"}} //ラッパーに高さ100%を指定
/>

cssファイルでgatsby-image-wrapperの親要素にあたるクラスfiguremax-height:100%;を与える。
高さは子要素のimgに合わせて設定。 メディアサイズごとのサイズ指定も追加しておく。


.hero figure img {
    width: 100%;
    height: 450px;
    object-fit: cover;
}
//追加
.hero figure {
    max-height: 100%;
    height: 450px;
}

@media (min-width: 768px) {
//追加
    .hero figure {
        height: 750px;
    }

    .hero figure img {
        height: 750px;
    }

背景画像を最適化する

背景画像として画像が使用されている場合はまず、CSSで背景画像を指定している部分をnoneへ変更。
JSXへ新しく背景画像を表示するためのマークアップを追加。

<footer>
  <div className="container">

  //もとからある要素....

    //追加
    <div className="back">
      <StaticImage
          src="../images/pattern.jpg"
          alt=""
          layout="fullWidth"
          style={{ height :"100%"}}
      />
    </div>
  </div>
</footer>

CSSで大きさを調整して、positionを指定。z-indexで重なりを調整する。

/*フッター背景画像*/
.footer{
    position: relative;
}

.footer .container{
    position: relative;
    z-index: 10;
}

.footer .back{
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}

画質が荒いとき

gatsby-config.jsqualityの調整をする。

  plugins: [
    {
      resolve: `gatsby-plugin-sharp`,
      options: {
        defaults: {
          quality: 90, //デフォルトは50
        },
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-image`,
  ],

今回は画像の最適化について書いてみました。
次回はコンポーネント化について書いて行きます。