画像をコピーもしくは圧縮する – npm + nunjucks + stylus で静的サイト制作を効率的にする(3)

npm + Nunjucks + stylusを使用してフォルダの変更を監視してhtml,css,jsを再生成、browserSyncを利用してブラウザを自動リロードして確認しやすいようにしました。

ただ画像ファイルの処理がないのでその処理を追加していきます。

画像ファイル処理については大体2つのルートを考えます。

  1. 画像は画像ソフトでひとつひとつ適切に圧縮する
  2. 画像は一括で圧縮してサイズを小さくする

画像をただコピーするパターン

1)の場合はコピーだけで済ませるだけで十分かと思っています。
その時は以下のコードをpakage.jsonに追加します

"build:img": "cpx \"src/img/**/*.{gif,png,jpg,svg,webp}\" dist/img/",
"watch:img": "chokidar \"src/img/**/.{gif,png,jpg,svg,webp}\" -c \"npm run build:img\""

これでsrc/imgディレクトリに保存されている画像ファイルをdist/imgディレクトリに吐き出せます。

2行目の処理でフォルダの変更を感知して生成を行っています。

すでに設定されているbuildコマンドを以下のように変更します。

▼変更前

"build": "run-s build:html build:stylus build:js"

▼変更後

"build": "run-s build:html build:img build:stylus build:js"

画像を圧縮するパターン

2)のパターンはimageminパッケージを使用して圧縮します。

画像の量が大量で写真のクオリティが最重要ではない場合はこちらの方が現実的です。

2ー1)必要なパッケージをインストールします。

npm i -D imagemin imagemin-keep-folder imagemin-mozjpeg imagemin-pngquant imagemin-gifsicle imagemin-svgo

パッケージについて

[imagemin-keep-folder]フォルダ構成を保持したまま処理できます
[imagemin-mozjpeg]jpgファイルを圧縮します
[imagemin-pngquant]pngファイルを圧縮します
[imagemin-gifsicle]gifファイルを圧縮します
[imagemin-svgo]svgファイルを圧縮します

imagemin処理はimagemin.jsファイルを作成して処理を記述しておきnpm-scriptで呼び出すようにします。

imagemin.jsファイルは以下のようになります。

const imagemin = require('imagemin-keep-folder');
const imageminMozjpeg = require('imagemin-mozjpeg');
const imageminPngquant = require('imagemin-pngquant');
const imageminGifsicle = require('imagemin-gifsicle');
const imageminSvgo = require('imagemin-svgo');

imagemin(['src/img/**/*.{gif,png,jpg,svg}'], {
  plugins: [
    imageminMozjpeg({ quality: 80 }),
    imageminPngquant({ quality: [0.7, 0.8] }),
    imageminGifsicle(),
    imageminSvgo()
  ],
  replaceOutputDir: output => {
    return output.replace(/img\//, './dist/img/')
  }
}).then(() => {
  console.log('圧縮完了');
});

imagemin.jsができたのでnpm-scriptに以下の処理を追加します。

"build:img": "node imagemin.js"

これで画像圧縮を自動化できました。

新しい画像フォーマットのwebpの使用も今後考えなければいけません。

その際は別の処理を追加しますがスケジュール的に余裕があればよいですが画像の差し替えなどはだいたいギリギリのタイミングだったり余裕のないときに処理が発生することが多いのでまだまだjpgフォーマットでの処理は続くと思っています。