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で生成する方法をメモしておこうと思います。
Can I Useで確認すると、2020年7月現在は以下のような対応状況です。
Safariは14から対応することが決まっていますので、今後は実質IE11以外はすべての主要なモダンブラウザに対応することになります。
ここからが本題です。
タスクランナー「Gulp」を使って、コマンド1発で画像を全部WebPに変換するタスクを書きます。
過去記事と同様にGulp4で書いていきます。
タスクファイルを分割する方法で書きますので、全体を知りたい方は過去記事をご覧ください。
タスクを書く場所はどこでも良いのですが、個人的に画像を圧縮するタスクなどをまとめています。
僕が使っている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画像かわからなくなってしまいます。
そのため生成ファイル画像にあえて拡張子を残した状態でファイル名を付けるようにします。
こうした対策のためにリネーム処理を通すことが必要になります。
ここまでで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
.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>
下記記事を参考にして対応しました。(丸投げ)
【画像で解説】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も直に対応することが決まっていますので、新規案件は特別な事情がない限りは必須対応になるかも。