Gatsby.jsの画像最適化プラグインgatsby-imageを触ってみてわかったこと。
Gatsby.jsの画像最適化プラグインgatsby-imageを触ってみてわかったこと。:
https://takumon.com/2018/10/21/#gatsby-image
@Takumon さんのwebページの記事を参考いたしました。gatsby.jsのプラグインがとても簡潔にまとめてあり勉強になりました。感謝を申し上げます。
今回は、gatsby.jsにおける画像の最適化を行ってくれるプラグインgatsby-imageについて、「実装したこと」「やりたかったこと」「できなかったこと」をまとめた記事です。
gatsby-config.jsでは、画像を入れておくディレクトリまでのパスを指定している。gatsby-imageはプラグインではなく、gatsby-transformer-sharpとgatsby-plugin-sharpに依存したライブラリなので、plugins:{}には記述する必要はない。
これが最初の実装。GraphQLでローカルファイル検索を行って、検索に合致した画像を表示するといった一連の手順をシンプルに実装している。
ここの部分において、画像を1つしか指定できていないことがわかる。
「1ページあたり1枚しか画像を使えないの…」みたいな疑問にぶち当たったのでGatsby.jsの公式レファレンスを読んでみた。
https://www.gatsbyjs.org/docs/graphql-reference/#aliasing
公式サイトのレファンレンスに書いてあるAliasingを用いれば、一度に複数のファイルを要求することができそう。と言うことで実装。
無事に表示できた。(今回は名前を変えただけで同じ画像を使ってる)
aliasingでは自由に名前を指定できるみたい。今回はlogo1とlogo2と言う名前を使ったけど、わかりやすい自分なりの名前をつけるとミスが起こらなくて済みそう。
ここに書いてあるようにStaticQueryを使って描画しているが、もう少し直感的に書きたい気持ちがある。ってことで別の記述方法で実装してみる。
よしよし、表示できている。
Gatsby.jsではStaticQueryを使わない場合は、propsの中に自動的に格納される。fixedの中身が少し変わっているので注意したい。全体的なコード量も少なくなっているのでいい感じ。
これが最後の挑戦。「GraphQLのクエリをいちいち書いているのなんてめんどくせぇ! 俺はパス指定だけで最適化したいんじゃ!」となったので挑戦。
※ここから少し長いです※
端的に言うとjavascriptのテンプレートリテラル周りでうまくいかなかった。
やりたかったこと↓
パスを指定するだけで動的にGraphQLクエリを生成し、ローカルにある画像の問い合わせを行う。しかしながら、これには弱点がある。
テンプレートリテラル内で式展開を行う場合、返ってくるのは
解決方法を探しに探したのですが、
結局は諦めることにしました。(←技術力不足)
色々ありましたが、gatsby-imageは面倒臭い画像最適化処理を全部やってくれる最高なライプラリです。この記事がgatsby.jsを使う際の参考になればと思います。
ここまで読んでくださり、ありがとうございました!
はじめに
https://takumon.com/2018/10/21/#gatsby-image @Takumon さんのwebページの記事を参考いたしました。gatsby.jsのプラグインがとても簡潔にまとめてあり勉強になりました。感謝を申し上げます。
今回は、gatsby.jsにおける画像の最適化を行ってくれるプラグインgatsby-imageについて、「実装したこと」「やりたかったこと」「できなかったこと」をまとめた記事です。
開発環境
◯ 基本環境
-
MacOS 10.14 -
Gatsby.js 2.0.76 ( https://www.gatsbyjs.org ) -
React.js 16.6.3 ( https://reactjs.org )
◯ プラグイン等
- gatsby-image
- gatsby-plugin-sharp
- gatsby-transformer-sharp
- gatsby-source-filesystem
gatsby-imageについて
公式サイトを読む
原文ママ
- Loads the optimal size of image for each device size and screen resolution
- Holds the image position while loading so your page doesn’t jump around as images load
- Uses the “blur-up” effect i.e. it loads a tiny version of the image to show while the full image is loading
- Alternatively provides a “traced placeholder” SVG of the image.
- Lazy loads images which reduces bandwidth and speeds the initial load time
- Uses WebP images if browser supports the format
日本語訳
- 各デバイスのサイズと画面解像度に最適なイメージサイズを読み込みます
- 画像の読み込み中に画像の位置を保持します
- 画像全体が読み込まれている間に表示する画像の小さな画像を読み込みます。
- レイジーは画像をロードして帯域幅を減らし、初期ロード時間を短縮します
- ブラウザーがその形式をサポートしている場合、WebPイメージを使用します。
※超意訳※
画像最適化周りの面倒臭いことは、プラグインが全部いい感じにやってくれます
実装部分
gatsby-config.js
module.exports = {
plugins: {
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
...(以下省略)
}
}
index.jsx
import React from 'react'
import { Link, StaticQuery, graphql } from 'gatsby'
import Img from 'gatsby-image'
import Layout from '../components/layout' // 詳細は割愛
const IndexPage = () => (
<StaticQuery
query={query}
render={ data => (
<Layout>
<div>
<Img fixed={data.file.childImageSharp.fixed}/>
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)}
/>
)
export default IndexPage
const query = graphql`
query {
file(relativePath: {eq: "logo.jpg"}) {
childImageSharp{
fixed(width: 200) {
...GatsbyImageSharpFixed
}
}
}
}
`
やりたかったこと
- 複数画像の表示
- 様々な記述方法で対応
- パス指定のみで表示できるようにしたい
1. 複数画像の表示
const query = graphql`
query {
file(relativePath: {eq: "logo.jpg"}) {
childImageSharp{
fixed(width: 200) {
...GatsbyImageSharpFixed
}
}
}
}
`
「1ページあたり1枚しか画像を使えないの…」みたいな疑問にぶち当たったのでGatsby.jsの公式レファレンスを読んでみた。
https://www.gatsbyjs.org/docs/graphql-reference/#aliasing
公式サイトのレファンレンスに書いてあるAliasingを用いれば、一度に複数のファイルを要求することができそう。と言うことで実装。
index.jsx
import React from 'react'
import { Link, StaticQuery, graphql } from 'gatsby'
import Img from 'gatsby-image'
import Layout from '../components/layout' // 詳細は割愛
const IndexPage = () => (
<StaticQuery
query={query}
render={ data => (
<Layout>
<div>
<Img fixed={data.logo1.childImageSharp.fixed}/>
<Img fixed={data.logo2.childImageSharp.fixed}/>
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)}
/>
)
export default IndexPage
const query = graphql`
query {
logo1:file(relativePath: {eq: "logo.jpg"}) {
childImageSharp{
fixed(width: 200) {
...GatsbyImageSharpFixed
}
}
},
logo2:file(relativePath: {eq: "logo2.jpg"}) {
childImageSharp{
fixed(width: 200) {
...GatsbyImageSharpFixed
}
}
}
}
`
無事に表示できた。(今回は名前を変えただけで同じ画像を使ってる)
aliasingでは自由に名前を指定できるみたい。今回はlogo1とlogo2と言う名前を使ったけど、わかりやすい自分なりの名前をつけるとミスが起こらなくて済みそう。
2. 様々な記述方法で対応
const IndexPage = () => (
<StaticQuery
query={query}
render={ data => (
<Layout>
<div>
<Img fixed={data.logo1.childImageSharp.fixed}/>
<Img fixed={data.logo2.childImageSharp.fixed}/>
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
)}
/>
)
index.jsx
import React from 'react'
import { Link, graphql } from 'gatsby'
import Img from 'gatsby-image'
import Layout from '../components/layout'
export default props => {
return <Layout>
<div>
<Img fixed={props.data.logo1.childImageSharp.fixed}/>
<Img fixed={props.data.logo2.childImageSharp.fixed}/>
</div>
<Link to="/page-2/">Go to page 2</Link>
</Layout>
}
export const query = graphql`
query {
logo1:file(relativePath: {eq: "logo.jpg"}) {
childImageSharp{
fixed(width: 200) {
...GatsbyImageSharpFixed
}
}
},
logo2:file(relativePath: {eq: "logo2.jpg"}) {
childImageSharp{
fixed(width: 200) {
...GatsbyImageSharpFixed
}
}
}
}
`
よしよし、表示できている。
Gatsby.jsではStaticQueryを使わない場合は、propsの中に自動的に格納される。fixedの中身が少し変わっているので注意したい。全体的なコード量も少なくなっているのでいい感じ。
3. パス指定のみで表示できるようにしたい
これが最後の挑戦。「GraphQLのクエリをいちいち書いているのなんてめんどくせぇ! 俺はパス指定だけで最適化したいんじゃ!」となったので挑戦。
…が、できなかった…
※ここから少し長いです※端的に言うとjavascriptのテンプレートリテラル周りでうまくいかなかった。
やりたかったこと↓
Img.jsx
import * as React from 'react'
import {graphql, StaticQuery} from 'gatsby'
import Image from 'gatsby-image'
const getQuery = path => {
return graphql`
query {
file(relativePath: {eq: "${path}"}) {
childImageSharp{
fixed(width: 200) {
...GatsbyImageSharpFixed
}
}
}
}
`
}
export default () => {
return <StaticQuery
query={ getQuery("logo.jpg") }
render={data => (
<Image fixed={data.file.childImageSharp.fixed}/>
)}
/>
}
graphqlの引数はTemplateStringsArrayという型であり、これは `` (テンプレートリテラル)を使った文字列のことを指しています。そしてこれには大きな落とし穴があって、const getQuery = path => {
return graphql`
query {
file(relativePath: {eq: "${path}"}) {
childImageSharp{
fixed(width: 200) {
...GatsbyImageSharpFixed
}
}
}
}
`
}
string型に変換されたものになってしまうのです。したがって、関数graphqlの引数の型が一致せずエラーになってしまう…解決方法を探しに探したのですが、
TemplateStringsArray型を引数に格納しようとあがいてもstring型に変換されてしまうのでどうしようもできず…結局は諦めることにしました。(←技術力不足)
まとめ
色々ありましたが、gatsby-imageは面倒臭い画像最適化処理を全部やってくれる最高なライプラリです。この記事がgatsby.jsを使う際の参考になればと思います。ここまで読んでくださり、ありがとうございました!
コメント
コメントを投稿