gulp環境ではgulp-imageminというパッケージを使うことで画像を圧縮できるようになります。
gulp-imageminは、
- 高い圧縮率で
- 画質の劣化もほとんどなく
- 簡単に(自動で)
画像を圧縮できるようになります。
今まで手動で圧縮していた人はその手間が丸々なくなるので開発効率がかなり上がること間違いなしです!
というわけで今回はgulp-imageminで画像を自動圧縮する方法を紹介します。コピペokです。
圧縮できる画像の種類は以下の通り。
- jpg/jpeg
- png
- gif
- svg
基本的な画像ファイルなら全部圧縮できますね。
gulp-imageminをインストール
gulpで画像を自動圧縮するのに必要なパッケージは以下の4つです。npmでサクッとインストールしちゃいましょう。
$ npm i -D gulp-imagemin
$ npm i -D imagemin-pngquant
$ npm i -D imagemin-mozjpeg
$ npm i -D gulp-changed
- jpg→mozjpeg
- png→pngquant
- gif/svg→imageminに入っているgifsicle/svgoというパッケージ
で圧縮できます。
gulp-changedは監視対象と出力先のディレクトリの差分を検出し、変更があったファイルのみを処理の対象にしてくれるパッケージです。新しい画像を入れたらその画像だけ圧縮処理をするみたいな感じです。
gulp-imageminの使い方
ディレクトリ構成
ディレクトリ構成はこんな感じです。
gulpfile.js
node_modules
dist/
└assets/
└images/
src/
└assets/
└images
画像はsrc/assets/images
に保存し、ここをwatchします。変更があったらgulp-imageminで画像を圧縮し、dist/assets/images
に出力します。
src
に画像を放り込むだけで自動で圧縮してくれるというわけですね。
gulpfile.jsに処理を書く
gulpfile.jsはこんな感じで書きます。ディレクトリだけ自分の環境に合うように書き換えてコピペしてもらえればそのまま動くはずです。
const imagemin = require('gulp-imagemin');
const mozjpeg = require('imagemin-mozjpeg');
const pngquant = require('imagemin-pngquant');
const changed = require('gulp-changed');
gulp.task("imagemin", function () {
return gulp
.src('./src/assets/images/**')
.pipe(changed('./dist/assets/images'))
.pipe(
imagemin([
pngquant({
quality: [.60, .70], // 画質
speed: 1 // スピード
}),
mozjpeg({ quality: 65 }), // 画質
imagemin.svgo(),
imagemin.optipng(),
imagemin.gifsicle({ optimizationLevel: 3 }) // 圧縮率
])
)
.pipe(gulp.dest('./dist/assets/images'));
});
// watch
gulp.task('default', function() {
gulp.watch('./src/assets/images/**', gulp.task('imagemin'));
});
changed
を使ってsrcとdistの差分を検出し、変更があった画像のみを処理の対象とします(changed
の引数に渡すのは出力先のディレクトリです)。
png
pngquant
でpngを圧縮します。
quality
には画質を配列で渡します。[.60, .70]
としたので、60〜70%程度の画質で圧縮するという感じです。これくらいの圧縮率なら画像サイズをかなり減らしつつ画質もほぼ劣化せずに圧縮できると思います。
古い記事だとqutlity: '65-80'
みたいに文字列で指定していますが、今は書き方が変わったのでこれだとエラーになります。地味にハマりポイントなので注意。
speed
は実行速度を指定します。1〜10まで指定でき、数が大きいほど実行速度が速いですが代わりに品質が落ちます。基本的に1にしておきましょう。
jpg
mozjpeg
でjpgを圧縮します。
quality
に画質を指定しましょう(pngquant
以外は渡す値は1つです)。
jpgは圧縮しすぎると画質の劣化が激しいので、自分で妥協点を見つけていい感じの圧縮率を指定しましょう。僕が指定している65だと画質は若干劣化するけど目視ではほぼわからないレベルです。これ以上下げるときついかも。不安な人は80くらいにしておくと安全です。
svg
svgo
でsvgを圧縮します。
圧縮前と圧縮後を比較するとこんな感じ。
圧縮前↓
圧縮後↓
コードが圧縮されているのがわかりますね。
svg自体そこまでサイズが大きいものはないと思いますが、ファイルサイズが減ることに越したことはないのでとりあえず圧縮しておきましょう。
gif
gifsicle
でgifを圧縮します。
optimizationLevel
で1〜7まで圧縮率を指定できます。僕は3にしていますが、かなりファイルサイズを減らしつつ画質の劣化はほぼ見られませんでした。3くらいがちょうどいいと思います。
watch
src/assets/images
をwatchすればokです。ここに画像が入った時に自動でimageminタスクが走り、画像を圧縮してdist/assets/images
に吐き出します。
ただ、画像をリネームした時も処理が走るので、何回もリネームしているとdistフォルダが散らかってきます。
そんな時は一旦distの画像を全部削除して、imageminを走らせるタスクを作ってしまいましょう。(del
を使うのでnpm i -D del
で先にインストールしてくださいね)
const del = require('del');
// distの画像全削除
gulp.task('delimg', function () {
return del('./dist/assets/images');
});
// dist画像全削除+src画像全コピー+圧縮
gulp.task('cleanimg', gulp.series(
'delimg',
'imagemin'
));
gulp cleanimg
で実行です。
cleanimg
の処理内容はdist内の画像をdel
で全削除→imagemin
実行(src内の画像を全て圧縮し、distに全部吐き出す)という感じです。
実行する際は新規ターミナルをもう1個開いて処理しておけば、開発を進めている間に勝手に終わります。時間もそこまでかかりません。
gulp-imageminで実際に圧縮した結果
実際に圧縮したらこんな感じになりました。
//png
gulp-imagemin: Minified 1 image (saved 305 kB - 78.4%)
Finished 'imagemin' after 1.76 s
//jpg
gulp-imagemin: Minified 1 image (saved 29.6 kB - 54.7%)
Finished 'imagemin' after 109 ms
//svg
gulp-imagemin: Minified 1 image (saved 1.89 kB - 14.2%)
Finished 'imagemin' after 105 ms
//gif
gulp-imagemin: Minified 1 image (saved 474 kB - 73.7%)
Finished 'imagemin' after 1.8 s
めちゃめちゃ圧縮できてる…!!
これだけ圧縮してるのに画質はほとんど劣化してません。しかも全部自動でやってくれるんだからすごい…!すごくね?
gulp-imageminで画像が圧縮されない?
僕がimageminをいじってる時、たまに画像が圧縮できない時がありました。
gulp-imagemin: Minified 0 images
Finished 'imagemin' after 70 ms
処理は走ってるけど圧縮されてない…画像情報を見てもファイルサイズが変わってない…。
この原因は「すでに一度圧縮しているから」でした。
一度gulp-imageminの処理を通した画像にもう一度処理をかけても圧縮はされないみたいですね。動作チェックしてると案外こういうところにハマるので気をつけましょう。
まとめ
gulp-imageminで画像を自動圧縮する方法を紹介しました。
今まで手動で画像を圧縮していた人はimageminを入れるとかなり手間が省けます。画像をフォルダに放り込むだけで自動で圧縮してくれるので開発効率もかなり上がりますよ!