WEB制作において、画像の最適化は重要な要素の一つです。
特に多くの画像を扱う場合、その処理に時間がかかり、ページの読み込み速度に影響を与えることがあります。
もちろんページの表示速度だけではなく、手作業で圧縮を行っていては、作業全体の速度も落ちてしまいます。
そこで今回は、Gulp5を使用して自動的に画像を圧縮する方法をご紹介します。
WEBデザイナーでなくても簡単に導入できるので、ぜひ試してみてください。
※Gulp自体の導入は他の記事をご覧ください。
Gulp5での自動画像圧縮の解決策
Gulp5を使用することで、画像の圧縮を自動化し、効率的にWEBサイトのパフォーマンスを向上させることができます。
さっそくですが、下記コードを使用すれば、画像の圧縮作業を自動化することが可能です。
import gulp from 'gulp'; // gulpをインポート
const { series, src, dest, watch } = gulp; // series, src, dest, watchがそのまま使えるように
// プラグインのインポート
import plumber from 'gulp-plumber'; // エラーが発生してもタスクを停止しない
import notify from 'gulp-notify'; // エラー発生時にデスクトップ通知を行う
import imagemin from 'gulp-imagemin'; // 画像ファイルを圧縮する
import mozjpeg from 'imagemin-mozjpeg'; // JPEG画像を圧縮する
import pngquant from 'imagemin-pngquant'; // PNG画像を圧縮する
import rename from 'gulp-rename'; // ファイル名を変更する
import log from 'fancy-log'; // ログを抑制するためのモジュール
import path from 'path'; // パス操作用
import through from 'through2'; // ストリーム操作用
let totalSizeBefore = 0;
let totalSizeAfter = 0;
// 参照元パス
const srcPath = {
img: 'src/image/**/*.{png,jpg,gif,svg}', // 画像ファイルのソース
};
// 出力先パス
const destPath = {
img: 'dist/image', // 画像ファイルの出力先
};
// 画像を圧縮するタスク
const compressImages = () => (
src(srcPath.img, { encoding: false }) // 画像ファイルのソース
.pipe(plumber({
errorHandler: (err) => {
notify.onError({
title: `Gulp error in ${err.plugin}`,
message: err.toString()
})(err);
}
})) // エラー時に通知
.pipe(through.obj(function(file, enc, cb) {
totalSizeBefore += file.stat.size; // 圧縮前のファイルサイズを累積
const sizeMB = file.stat.size / (1024 * 1024); // ファイルサイズをMB単位で取得
let imageminPlugins;
if (sizeMB > 2) { // 2MB以上のファイル
imageminPlugins = [
mozjpeg({ quality: 50, progressive: true }), // JPEGの圧縮
pngquant({ quality: [0.4, 0.5] }), // PNGの圧縮
];
} else if (sizeMB > 1) { // 1MB以上2MB未満のファイル
imageminPlugins = [
mozjpeg({ quality: 65, progressive: true }), // JPEGの圧縮
pngquant({ quality: [0.5, 0.6] }) // PNGの圧縮
];
} else { // 1MB未満のファイル
imageminPlugins = [
mozjpeg({ quality: 75, progressive: true }), // JPEGの圧縮
pngquant({ quality: [0.6, 0.8] }) // PNGの圧縮
];
}
gulp.src(file.path, { encoding: false })
.pipe(imagemin(imageminPlugins, { verbose: false })) // verbose: false で詳細なログを抑制
.pipe(rename((filePath) => {
filePath.dirname = path.relative(file.base, path.dirname(file.path)); // 元のディレクトリ構造を保持
}))
.pipe(dest(destPath.img))
.on('data', (data) => {
totalSizeAfter += data.stat.size; // 圧縮後のファイルサイズを累積
})
.on('end', () => cb());
}))
);
// 画像処理タスクを一つにまとめる
const imgTask = series(compressImages, (done) => {
const totalReduction = ((totalSizeBefore - totalSizeAfter) / totalSizeBefore) * 100;
log.info(`Total size before compression: ${(totalSizeBefore / (1024 * 1024)).toFixed(2)} MB`);
log.info(`Total size after compression: ${(totalSizeAfter / (1024 * 1024)).toFixed(2)} MB`);
log.info(`Total size reduction: ${((totalSizeBefore - totalSizeAfter) / (1024 * 1024)).toFixed(2)} MB`);
log.info(`Total size reduction percentage: ${totalReduction.toFixed(2)}%`);
done();
});
// ファイルの変更を監視するタスク
const watchFiles = (done) => {
watch(srcPath.img, imgTask); // 画像ファイルが変更されたら圧縮する
done();
};
// デフォルトタスク(Gulpを実行した際に動くタスク)
export default series(imgTask, watchFiles);
コードの内容については記事の続きで解説していきます。
画像の圧縮設定
このコードでは画像のサイズに応じて圧縮率を変更する設定が含まれています。
Gulpでの圧縮を検索していて見つかるのは圧縮率が変動しない形、70%と決めたら軽いファイルであろうが重たいファイルであろうがクォリティを70%保つ形での圧縮をする、といったコードを多く見かけます。
今回は、多くの人が公開していないようなユニークな形で以下のように容量によって圧縮率が変動するような設定をしました。
- 2MB以上のファイル: JPEGは50%の品質で圧縮、PNGは40%-50%の品質で圧縮
- 1MB以上2MB未満のファイル: JPEGは65%の品質で圧縮、PNGは50%-60%の品質で圧縮
- 1MB未満のファイル: JPEGは75%の品質で圧縮、PNGは60%-80%の品質で圧縮
上記の設定を変更したい場合、以下のコード部分を修正します:
if (sizeMB > 2) { // 2MB以上のファイル
imageminPlugins = [
mozjpeg({ quality: 50, progressive: true }), // JPEGの圧縮
pngquant({ quality: [0.4, 0.5] }), // PNGの圧縮
];
} else if (sizeMB > 1) { // 1MB以上2MB未満のファイル
imageminPlugins = [
mozjpeg({ quality: 65, progressive: true }), // JPEGの圧縮
pngquant({ quality: [0.5, 0.6] }) // PNGの圧縮
];
} else { // 1MB未満のファイル
imageminPlugins = [
mozjpeg({ quality: 75, progressive: true }), // JPEGの圧縮
pngquant({ quality: [0.6, 0.8] }) // PNGの圧縮
];
}
上記コードの quality
パラメータを変更することで、各ファイルサイズに応じた圧縮品質を調整できます。
数字を変更してみて、圧縮されたファイルをみてテストを繰り返す中でお好みの数値を決められるのがいいかもしれません。
エラー処理
エラー処理の設定は、圧縮処理中にエラーが発生した場合に通知を行うためのものです。
これにより、すぐに対応することが可能です。。。といっても特にこれといった珍しいことはしていないです。
.pipe(plumber({
errorHandler: (err) => {
notify.onError({
title: `Gulp error in ${err.plugin}`,
message: err.toString()
})(err);
}
})) // エラー時に通知
圧縮プラグインの使用
JPEG画像の圧縮には imagemin-mozjpeg
、PNG画像の圧縮には imagemin-pngquant
を使用しています。
これにより、高効率な画像圧縮が実現できます。
import imagemin from 'gulp-imagemin'; // 画像ファイルを圧縮する
import mozjpeg from 'imagemin-mozjpeg'; // JPEG画像を圧縮する
import pngquant from 'imagemin-pngquant'; // PNG画像を圧縮する
SVGとGIFの圧縮について
今回の設定では、SVGとGIFの圧縮は含まれていません。
少し残念ですが、私の実力不足で、SVGとGIFを入れてしまうとうまく動かすことができませんでした。
これらのファイルが元々軽量であるため、圧縮の必要性が低いと判断したため今回は断念をしていますが。
今後対応していけるようにチャレンジしていきたいと考えています。
圧縮後のディレクトリ構造の保持
圧縮後も元のディレクトリ構造を保持するための設定も含まれており、ファイルの管理が容易になります。
.pipe(rename((filePath) => {
filePath.dirname = path.relative(file.base, path.dirname(file.path)); // 元のディレクトリ構造を保持
}))
この部分も色々検索をしてみると、ディレクトリに分けずimageディレクトリ直下にごっそり入れている方を多く見かけました、自分も実際そうしていたりもするのですが、imageディレクトリの配下でページ名でディレクトリを分けていたりカテゴリで分けている方プラグインのものだけ分けている方などもいらっしゃるかと思い、ディレクトリ構造を保持されるようにしました。
ディレクトリ例
かなりざっくりになりますが、srcに保存されたのがそのままdistの方に圧縮して出力されるような形です。
distディレクトリに圧縮されたものが出力される。
├── dist/
│ └── image/
│ ├── common/
│ └── parts/
│ ├── *.jpg
│ └── *.png
│
└── src/
└── image/
├── common/
└── parts/
├── *.jpg
└── *.png
ディレクトリを変更したい場合は下記の個所を調節するだけで可能ですので、是非環境に合わせて調節いただけたらと思います。
// 参照元パス
const srcPath = {
img: 'src/image/**/*.{png,jpg,gif,svg}', // 画像ファイルのソース
};
// 出力先パス
const destPath = {
img: 'dist/image', // 画像ファイルの出力先
};
Gulp5の活用例
この自動画像圧縮の設定はWEB制作だけでなく、わざわざ圧縮サイトにアクセスするのが面倒な人にもおすすめです。
ローカルで簡単に画像を最適化できるため、作業効率が大幅に向上します。
まとめ
Gulp5を使用することで、画像の圧縮作業を自動化しWEBサイトのパフォーマンスを向上させることができます。
ファイルサイズに応じた圧縮率の設定やエラー処理、ディレクトリ構造の保持など、使いやすさにも配慮した設定となっています。
ぜひ一度試してみてください。
この設定を導入することで、日々のWEB制作がより快適になり、効率的に作業を進めることができるでしょう。