Gulpを使ってWebP画像を生成する方法【Gulp4】

Gulpを使ってWebP画像を生成する方法【Gulp4】

WebP(ウェッピー)とは?

Googleが開発している画像フォーマットのことです。ファイルの拡張子は「.webp」になります。

一般的にWebで広く扱われているJPEGやPNGよりも容量を小さくできます。具体的にはJPEG・PNGと比較して25 〜 35%小さくできます。小さくなるからといって画質が悪くなることはありません。また、PNGと同じく透明部分も画像として反映されます。

PageSpeed InsightsやChrome DevToolsなんかで「Lighthouse」による診断をしてみると、「Serve images in next-gen formats(次世代フォーマットで画像を提供してください)」といった診断が出ることがありますが、WebPがその次世代フォーマットに当たります。

少し前までは「サイトの表示高速化」については今ほど注目されていませんでしたが、最近は「サイトの表示高速化」がSEOにも繋がるようになってきましたし、各ブラウザの対応状況も変わってきて、今後作成するサイトではWebP対応しておいた方が良い状況になってきました。

今回はそんなWebP画像をGulpで生成する方法をメモしておこうと思います。

WebPの対応ブラウザ

Can I Useで確認すると、2020年7月現在は以下のような対応状況です。

WebP対応ブラウザ一覧
https://caniuse.com/#search=webp
  • Edge
  • Firefox
  • Chrome
  • Safari(14から)
  • iOS Safari(14から)
  • Android Browser

Safariは14から対応することが決まっていますので、今後は実質IE11以外はすべての主要なモダンブラウザに対応することになります。

Gulpで画像をWebPに変換

ここからが本題です。

タスクランナー「Gulp」を使って、コマンド1発で画像を全部WebPに変換するタスクを書きます。

過去記事と同様にGulp4で書いていきます。
タスクファイルを分割する方法で書きますので、全体を知りたい方は過去記事をご覧ください。

Gulpタスクを書く

タスクを書く場所はどこでも良いのですが、個人的に画像を圧縮するタスクなどをまとめています。

僕が使っているgulpfileの構成は下記の通りになっていますので、img.jsにタスクを追記していきます。

gulpfile.babel.js //「gulpfile.babel.js」という名称のディレクトリを作る
├── /tasks
     ├── browsersync.js
     ├── css.js
     ├── html.js
     ├── img.js  //ここにWebP生成タスクを追加する
     ├── js.js
     ├── svg.js
     └── watch.js
├── config.js
├── index.js
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js

.babelrc
package.json

パッケージのインストール

まずは必要なパッケージをインストール。

$ yarn add -D gulp-webp gulp-rename

設定ファイルの調整

次に設定ファイルを調整します。

config.jsにパスやglob(ファイル名のパターンマッチング)を全部設定して使いまわせるようにしているので、そこに画像フォルダの設定も追記しておきます。

export const paths = {
  jsDir    : path.join(__dirname, '../assets/js'),
  sassDir  : path.join(__dirname, '../assets/sass'),
  imageDir : path.join(__dirname, '../assets/images'), //追記
  ...
}

export const globs = {
  js      : `${paths.jsSrcDir}/**/*.+(js|vue)`,
  sass    : `${paths.sassDir}/**/*.scss`,
  img     : `${paths.imageDir}/**/*.+(jpg|jpeg|png|gif|svg)`, //追記
  ...
}

タスクを追記

そしてimg.jsにタスクを追記します。
先ほどインストールしたパッケージを使います。gulp-webpでWebPの生成、gulp-renameで生成するファイルの名称を変更します。Gulp4で書きます。

import gulp from 'gulp';
import { globs, paths } from '../config.js';

import gulpWebp from 'gulp-webp';
import rename from 'gulp-rename';

function webp() {
  return gulp
  .src(globs.img,{
    allowEmpty : true,
    since      : gulp.lastRun('webp')
  })
  .pipe(rename((path) => {
    path.basename += path.extname;  //生成ファイルのリネーム
  }))
  .pipe(gulpWebp()) //WebPの生成
  .pipe(gulp.dest(paths.imageDir));
}
exports.webp = webp;

ファイルのリネームは必要?

ここでポイントとなるのがリネーム処理の部分です。

リネームの処理を通さずにgulp-webpで画像を生成すると「sample.jpg」という画像は「sample.webp」という画像に変わります。

一見すると問題無さそうに見えますね。

ですが、「sample.png」「sample.gif」という別の拡張子が付いたファイルも同じディレクトリにあったとすると、それらすべてが「sample.webp」を生成してしまいます。これだとどのファイルのWebP画像かわからなくなってしまいます。

そのため生成ファイル画像にあえて拡張子を残した状態でファイル名を付けるようにします。

  • sample.jpg → sample.jpg.webp
  • sample.png → sample.png.webp
  • sample.gif → sample.gif.webp

こうした対策のためにリネーム処理を通すことが必要になります。

タスクを登録する

ここまででWebP生成タスクが出来ましたが、このままでは動かないので最後の仕上げです。

index.jsに追記します。

import { webp } from './tasks/img'
exports.webp = webp;

上記のようにファイル分割したタスクモジュールをindex.jsにインポートしてexportsするだけです。

これでターミナルに下記のようにコマンドを打ち込むと、指定した画像フォルダにWebPが生成されます。

$ yarn gulp webp

package.jsonのscriptsにコマンドを書いておくとさらに短くできます。

"scripts": {
  "webp": "gulp webp",
}

こうすると毎回「gulp」は書かなくても良くなります。

$ yarn webp

サイトをWebP対応する方法

.htaccessに追記して対応させる方法を使います。
下記の記事を参考にさせていただきました。

【画像軽量化】WebPにそろそろ対応したほうが良さそうなので現時点で最適方法の考察 | 株式会社WEB企画

https://webkikaku.co.jp/homepage/blog/hpseisaku/htmlcss/webp-how-to-use/
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP_ACCEPT} image/webp
  RewriteCond %{SCRIPT_FILENAME}.webp -f
  RewriteRule .(jpe?g|png|gif)$ %{SCRIPT_FILENAME}.webp [T=image/webp]
</IfModule>

<IfModule mod_mime.c>
  AddType image/webp .webp
</IfModule>

<IfModule mod_setenvif.c>
  SetEnvIf Request_URI "\.(jpe?g|png|gif)$" _image_request
</IfModule>

<IfModule mod_headers.c>
  Header append Vary Accept env=_image_request
</IfModule>

WordPressの場合

下記記事を参考にして対応しました。(丸投げ)

【画像で解説】EWWW Image OptimizerでWebPを設定する方法

https://re-lifework.com/ewww-image-optimizer-webp

個人的にWordPress案件が多いので、対応するとなれば「EWWW Image Optimizer」を使って、テーマファイル内の画像はGulpで、メディアにアップロードする場合はプラグインで自動生成させるようにしています。

参考記事中にもありますが「EWWW Image Optimizer」では下記のような.htaccessへの記述を自動的に生成してくれる機能があります。

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} (.*)\.(jpe?g|png)$
RewriteCond %{REQUEST_FILENAME}\.webp -f
RewriteCond %{QUERY_STRING} !type=original
RewriteRule (.+)\.(jpe?g|png)$ %{REQUEST_FILENAME}.webp [T=image/webp,E=accept:1,L]
</IfModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REDIRECT_accept
</IfModule>
AddType image/webp .webp

他にも<picture>タグを使ってソースコード上から調整する方法もありますが、めちゃくちゃ記述増えて面倒くさいのでおすすめしません。

.htaccessで対応する方法だとWebP画像がない時は通常のPNGやJPG画像を表示してくれますし、対応していないブラウザのことも考えなくて良いので最適だと思います。

さいごに

今回はWebPについてのメモでした。

非力なレンタルサーバーなどを使っていると、画像の多いサイトでは転送量など気になるところですので、細かいですがこういう対応をしていく必要もあるかと思います。

Safariも直に対応することが決まっていますので、新規案件は特別な事情がない限りは必須対応になるかも。