LoginSignup
7

posted at

updated at

Organization

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

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

参考サイト

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
What you can do with signing up
7