LoginSignup
19
9

EJSにwebp生成と画像圧縮の自動化を追加する

Last updated at Posted at 2023-05-25

node.jsで画像の圧縮とwebp生成を自動化するをEJSテンプレートに追加しました。
figmaから書き出し→サルワカなどのサイトでwebpに変換...:innocent:の作業なくなり、効率がぐんと上がりました。

今回はその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!");
});
  1. imagemin-keep-folderであるimageminに変数にしておいた圧縮したい画像パスsrcDirを指定しています
  2. plugins: [~に圧縮処理をしてくれるパッケージを記載しています。
    plugins:use:の複数用なだけなのかuseをpluginsに変えても処理が通りました。
  3. replaceOutputDir: で圧縮後の画像のフォルダ構造を、/img/から2階層上の../../dist/assets/img/にカスタマイズされてます。
  4. プロミスチェーンで、圧縮後の画像を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

参考サイト

19
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
9