textlintやsharp使用時はonchangeでファイル監視すると便利

onchangeとは

globパターンを使ってファイルを監視し、追加、変更、削除されたときにコマンドを実行します。

textlintやsharpはwatchオプションがないため、ファイルを監視して変更されるたびに実行することはできないが、onchangeを使えばファイル監視が簡単にできるようになる。

onchange + textlint の使い方

まずonchangeとtextlintをインストールする。

テストのため「ら抜き言葉」をチェックするtextlint-rule-no-dropping-the-raもついでにインストールします。

npm i -D onchange textlint textlint-rule-no-dropping-the-ra

インストールしたら.textlintrcファイルを作成してrulesに「"no-dropping-the-ra": true」を書いて有効にします。

{
  "rules": {
    "no-dropping-the-ra": true
  }
}

以上の手順が終わったら「npx textlint **/*.txt」を実行すればtextlintを実行してテキストをチェックできます。

例えば以下のような文章がfoo.txtに含まれるとエラーになります。

npx textlint **/*.txt

/Users/iwbjp/my-onchange/foo.txt
  1:8  error  ら抜き言葉を使用しています。  no-dropping-the-ra

✖ 1 problem (1 error, 0 warnings)

これだと毎回「npx textlint **/*.txt」を実行しなければならないのでテキストの保存のたびに実行するのは面倒です。

しかし、以下のようにpackage.jsonのscriptsにnpm run textlintが実行できるよう追記後、onchangeを組み合わせて実行すればファイル監視により上書き保存するたびに「npx textlint **/*.txt」が実行されます。

"scripts": {
  "textlint:watch": "onchange '**/*.txt' -- npx textlint {{changed}}"
},
npm run textlint:watch

onchange + sharp の使い方

まずonchangeとsharpをインストールする。

ファイルの削除がわかりやすいようcolorsもインストールしてください。

npm i -D onchange sharp colors

この例では「src/img」にPNGまたはJPGが追加または修正が発生したら「dist/img」に書き出すコードを記述しています。

まずpackage.jsonのscriptsにsharp:watchを以下のように追記する。

"scripts": {
  "sharp:watch": "onchange 'src/img/**/*.{png,jpg,jpeg}' -- node sharp.mjs {{changed}}"
},

次にpackage.jsonに書いてあるsharp.mjsのファイルを新規作成して中身を以下のようにします。

import fs from 'fs';
import path from 'path';
import colors from 'colors';
import sharp from 'sharp';

const dirName = path.dirname(process.argv[2]);
const srcName = path.basename(process.argv[2]);
const srcNameWebp = srcName.replace(/\..+$/, '.webp');
const srcExt = path.extname(srcName).slice(1);
const srcPath = `${dirName}/${srcName}`;
const distDir = dirName.replace(/^src\/img/, 'dist/img');

if (!fs.existsSync(distDir)) {
  fs.mkdirSync(distDir);
}

if (['png', 'jpg', 'jpeg'].includes(srcExt)) {
  const file = await sharp(srcPath);
  const webp = file.webp({ quality: 60 });

  webp.toFile(`${distDir}/${srcNameWebp}`, (err, info) => {
    if (info) {
      const stats = fs.statSync(srcPath);
      const fileSize = stats["size"];
      console.log(`${srcPath}をwebpに変換しました。 ${fileSize / 1000} KB => ${info.size / 1000} KB`);
    } else if (err) {
      if (fs.existsSync(`${distDir}/${srcNameWebp}`)) {
        fs.unlinkSync(`${distDir}/${srcNameWebp}`);
        console.log(colors.red(`${srcPath}を削除しました。`));
      }
    }
  });
}

あとは「npm run sharp:watch」を実行すれば画像が追加・修正されるたびにWebP形式の画像がdist/imgに書き出されるようになります。

npm run sharp:watch
npm run sharp:watch実行後のターミナル画面
npm run sharp:watch実行後のターミナル画面