こんにちは。今回はWordpressから取得した記事内の画像にgatsby-imageを適用する方法を書いていきます。

gatsby-imageについて

一言でいうと「画像をいい感じに処理してくれるラッパー」です。サイトの速度を上げるには容量が重い画像の処理をどうするかが課題になってきます。その対処法として画像を遅延読み込み(Lazy Load)させたり、画像フォーマットを変更したり(WebP)、画像サイズを画面幅によって最適化するなどの方法があります。しかし、これを1から実装するのは非常に骨が折れます。そんな面倒な処理をやってくれるのがgatsby-imageです。gatsby-imageは画像をラップするだけで画像にlazy-load、レスポンシブを実装してくれたりと便利なものになっています。導入は以下のコードで導入できます。

bash
1
npm install --save gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp

そしてgatsby-config.jsに以下を追記します。

javascript
1
plugins: [`gatsby-transformer-sharp`, `gatsby-plugin-sharp`]

今回はそんなgatsby-imageをWordPressから取得した画像に適用していきたいと思います。ステップとして、

  1. 引数として渡したパスを元にgatby-imageを適用するcomponentを作成する。
  2. 最適化された画像を元の画像と差し替える。

という2ステップで書いていきます。

1. gatby-imageを適用するcomponent

ソースコードは以下のようになります。参考にしたサイトのものとほぼ同じです。

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import Img from 'gatsby-image'

const GatsbyImage = ({ src, alt = '', width, height }) => {
  const { allWordpressWpMedia } = useStaticQuery(allMedia)
  const originalSource = src.replace(
    /^(http?s:\/\/.+?\/.+?)-(\d+x\d+)\.(.+?)$/g,
    '$1.$3'
  )
  const image = allWordpressWpMedia.edges.find(
    ({ node }) => node.source_url === originalSource || node.source_url === src
  )

  if (!image) return <img src={src} alt={alt} />
  else if (!image.node.localFile) return <img src={src} alt={alt} />

  return (
    <Img
      sizes={image.node.localFile.childImageSharp.sizes}
      alt={alt}
      style={{
        maxWidth: '800px',
        marginRight: 'auto',
      }}
      fadeIn={false}
    />
  )
}

export default GatsbyImage

const allMedia = graphql`
  query {
    allWordpressWpMedia {
      edges {
        node {
          path
          source_url
          localFile {
            url
            childImageSharp {
              sizes(maxWidth: 800) {
                ...GatsbyImageSharpSizes
              }
            }
          }
        }
      }
    }
  }
`

GraphQLでWordPressのすべての画像を引っ張ってきて、GatsbyImageSharpSizesで画像の最適化を行います。WordPressでアップロードした画像はいくつかのサイズに変換されて保存されるため、「xxx.jpg」という名前のファイルが「xxx_100x100.jpg」「xxx_200x200,jpg」といった名前で保存されます。今回の場合はgatsby-imageに画像のリサイズを行わせたいので、オリジナルのファイル、つまり「xxx.jpg」を参照するようにします。

javascript
1
2
3
4
const originalSource = src.replace(
    /^(http?s:\/\/.+?\/.+?)-(\d+x\d+)\.(.+?)$/g,
    '$1.$3'
  )

この正規表現の部分でオリジナルの画像を参照するようにしています。あとはそのオリジナルの名前と一致した画像をgatsby-imageで最適化して返してあげるだけです。

以上で下準備はできました。後はこのコンポーネントを元の記事の画像と差し替えます。

2. 最適化された画像を元の画像と差し替える。

記事内の画像の差し替えには「html-react-parser」を使います。基本的には前回書いた記事と同じです。

以下がソースコードです。

jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import React from 'react'
import parse, { domToReact } from 'html-react-parser'
import GatsbyImage from './gatsbyImage'

const ContentParser = ({ content }) => {
  return <div>{parse(content, { replace: replaceCode })}</div>
}

const replaceCode = node => {
  if (node.name === 'p') {
    const image = getImage(node)
    if (image != null) {
      return (
        <GatsbyImage
          src={image.attribs.src}
          alt="article_pic"
          width={image.attribs.width}
          height={image.attribs.height}
        />
      )
    }
  }
}

const getImage = node => {
  if (node.name === 'img') {
    return node
  } else if (node.children != null) {
    for (let index = 0; index < node.children.length; index++) {
      let image = getImage(node.children[index])
      if (image != null) return image
    }
  }
}

export default ContentParser

WordPressでは画像はpタグで囲われているので、pタグについて画像が無いか探索します。html-react-parserでpタグを取り出して画像があるかを再帰で探索しています。

以上でWordPressから取得した画像にgatsby-imageを適用できます。以下に掲載した参考サイトも大変参考になるので読んで見て下さい。

以上です。お読みいただきありがとうございます。またよろしくおねがいします。

参考

https://qiita.com/tkkrr/items/34f384956fb968a30fe5
https://dimitr.im/optimize-loading-images-wordpress-gatsby
https://takumon.com/simple-gatsby-image-wrapper


2020.04.20 16:48  2020.05.03 03:02