O hirunewani blog

コミット前に画像を圧縮させる

Created at

sharpを使って画像を圧縮するスクリプトを、lefthookを利用して画像をコミット前に圧縮させる方法について紹介する。

画像を圧縮するスクリプト

画像を圧縮するライブラリに今回はsharpを利用した。

本当はWebPなどに変換した方が圧縮効率は遥かに高いが、Markdownに画像を埋め込んでおりパスを書き換えさせるスクリプトも作るのが面倒だったので、今回は1200x1200px以内に画像をリサイズするだけに留めている。

import { readFile } from "node:fs/promises";
import sharp from "sharp";

const minifyFile = async filename => {
  try {
    const sourceData = await readFile(filename);
    const info = await sharp(sourceData)
      .resize({
        width: 1200,
        height: 1200,
        fit: sharp.fit.inside,
        // このオプションをtrueにすると、元画像よりも小さい場合はリサイズしない
        withoutEnlargement: true,
      })
      .toFile(filename);

    console.log({
      filename: filename,
      beforeSize: sourceData.length,
      afterSize: info.size,
    });
  } catch (error) {
    throw error;
  }
};

try {
  const files = process.argv.slice(2);
  const promises = files.map(minifyFile);
  await Promise.all(promises);
} catch (error) {
  console.log(error);
  process.exit(1);
}

Lefthookでコミット前に画像を圧縮させる

LefthookはGitフックを管理するツールで、コミットなどをトリガーに特定のスクリプトを実行させることができる。

同種のツールとしてはHusky + Lint Stagedがある。個人的にはNode.js以外の環境でも導入しやすく、比較的エッジケースの少ないと思われるLefthookの方を好んで利用している。

lefthook.ymlで次のような設定を行い、コミット前に画像を圧縮させるようにした。

pre-commit:
  parallel: true
  commands:
    compress-images:
      tags: frontend
      glob: "*.{png,jpg,jpeg,webp}"
      run: node ./scripts/compress-image.js {staged_files} && git add {staged_files}