node.jsで画像の圧縮とwebp生成を自動化するをEJSテンプレートに追加しました。
figmaから書き出し→サルワカなどのサイトでwebpに変換...の作業なくなり、効率がぐんと上がりました。
今回はそのjsを読み解いていこうとおもいます。
パッケージのインストール
下記パッケージをインストールします。
nodeは16.0.0
にバージョンアップしました。
{
"imagemin-keep-folder": "^5.3.2",
"imagemin-mozjpeg": "^10.0.0",
"imagemin-pngquant": "^9.0.2",
"imagemin-svgo": "^9.0.0",
"imagemin-webp": "^6.0.0",
}
ターミナルで下記コマンドを打つとインストールされます
npm install --save-dev imagemin-keep-folder imagemin-pngquant@9.0.0 imagemin-webp@6.0.0 imagemin-svgo@9.0.0 imagemin-mozjpeg imagemin-gifsicle
プロジェクト直下に imagemin.js を作成
imagemin.jsに処理内容をかいていきます。
パッケージをインポート
node.jsで画像の圧縮とwebp生成を自動化するでは、require()
を使ってますが、requireはESモジュールスコープで定義されていませんので、代わりにimportを使用してください。
というエラーになってしまったので、言われるがままにimport
で対応しました。
また、import
を使うためにpackage.jsonに"type": "module",
を追記しました。
import imagemin from 'imagemin-keep-folder';
import imageminPngquant from 'imagemin-pngquant';
import imageminWebp from 'imagemin-webp';
import imageminSvgo from 'imagemin-svgo';
import imageminMozjpeg from 'imagemin-mozjpeg';
import imageminGifsicle from 'imagemin-gifsicle';
画像のパスを変数化
画像のパスを変数にしておきます。
//圧縮したい画像パス
const srcDir = "./src/assets/img/**/*.{jpg,jpeg,png,gif,svg,ico}";
//圧縮された画像の行く先パス
const outDir = "./dist/assets/img/**/*";
webp生成のための関数を定義
const convertWebp = (targetFiles) => {
imagemin([targetFiles], { // パッケージ:imagemin-keep-folder使用
use: [imageminWebp({ quality: 50 })], // パッケージ:imagemin-webp使用
});
};
imagemin
とは最初にimportしたパッケージのimagemin-keep-folder
です。
ディレクトリ構造を維持した状態で、吐き出し先に最適化した画像群を送ってくれます。
画像パスとして引数[targetFiles]
が指定されています。
最適化の処理としてuse: [imageminWebp(~
の部分で、パッケージのimagemin-webp
を使ってwebpを生成しています。
※quality(デフォルトは75)は指定しないとまれに処理が通らない場合があるそうです。50が丁度いいみたい
処理
imagemin([srcDir], { // 1. 圧縮したい画像パスを指定
plugins: [ // 2. 圧縮処理をするパッケージを記載
imageminMozjpeg(),
imageminPngquant(),
imageminGifsicle(),
imageminSvgo(),
],
replaceOutputDir: (output) => { // 3. フォルダー構造をカスタマイズ
return output.replace(/img\//, "../../dist/assets/img/");
},
}).then(() => { // 4. プロミスチェーンで下記処理をつなげる
convertWebp(outDir);
console.log("Images optimized!");
});
-
imagemin-keep-folder
であるimagemin
に変数にしておいた圧縮したい画像パスsrcDir
を指定しています -
plugins: [~
に圧縮処理をしてくれるパッケージを記載しています。
※plugins:
はuse:
の複数用なだけなのかuseをpluginsに変えても処理が通りました。 -
replaceOutputDir:
で圧縮後の画像のフォルダ構造を、/img/
から2階層上の../../dist/assets/img/
にカスタマイズされてます。 - プロミスチェーンで、圧縮後の画像をwebp変換する
convertWebp(outDir);
と、コンソールに「Images optimized!」を出力する処理をつなげています。
EJSに imagemin.js の自動実行を追加
imgを監視して自動で imagemin.js を実行するように package.json に追加しました。
"watch:img": "chokidar \"src/assets/img/**/*\" -c \"node imagemin.js\" --initial",
chokidar \" 監視対象のファイル \" -c \" 監視対象ファイルが変更したあとに実行するコマンド \" -–initial
-c
はcommandの略、--initial
はwatchコマンド実行後にスクリプトを1回実行するという意味です。
EJS CLIでEJSを自動コンパイルする方法 | zumilog
<symbol>
を使ったSVG画像の圧縮がうまくいかない
<symbol>
で囲んだSGVを<use>
で出力させSVG画像を使い回す方法をよくやるのだが、これを圧縮すると、SVGコードが消えてしまいました。
SVGはもともと軽いし...ということで、一旦imagemin-svgo
のSVGの圧縮はしないで使用しています。
【SVG画像】1つの画像ファイルで複数の色違い画像を使いまわす - Qiita
参考サイト