npm scripts で rimraf を使わずディレクトリを再帰的に削除する
3 行で
- Node.js >= v14.14.0 であること
-
rimraf dist
はnode -e 'fs.rmSync(`dist`, {recursive:true, force:true})'
で置き換えられる -
rimraf dist/*.bundle.js
みたいな glob を含むものは置き換えできない
長い説明
npm scripts で不要なキャッシュやビルドの出力ファイルを削除したい場合は rimraf
というパッケージを POSIX の rm -rf
の代わりに使うことが多いと思います。これは Windows で npm run
の実行に使われる コマンドプロンプト (cmd.exe) に rm
がないのを始めとした環境依存の問題を避けるためです。
とはいえパッケージなしではディレクトリの再帰的削除もできない、というのはちょっと困るので、v12.10.0 で fs.rmdir
fs.promises.rmdir
fs.rmdirSync
に recursive
オプションが追加され、fs.rmdirSync('foo/', { recursive: true })
とすることで rm -rf
や rimraf
に近いことができるようになりました。ちなみに、glob が使えないこと以外は rimraf がそのまま使われています。
しかし、実は POSIX の rmdir
には再帰的削除の機能がないため、recursive
を rmdir
のオプションに追加するとややこしくなるという意見があったようです。代替案として rmtree
という関数の追加とかが考えられたようです。また、POSIX との整合性で言うと rm
に相当するのが fs.unlink
になっていてややこしいといった問題もありました。
そこで、v14.14.0 で POSIX の rm
に相当する fs.rm
fs.promises.rm
fs.rmSync
が追加されました。Linux のシェルで rm -rf
とするように、fs.rmSync('foo/', { recursive: true, force: true })
とすることでディレクトリを再帰的に削除できます。
ということで、fs.rmSync
するコードを文字列として node --eval
(node -e
) に渡してディレクトリを削除できます。node -e
や node -p
では REPL と同じく fs
のインポートは不要です。また、fs.rmSync
にした理由は、fs.rm
は ,()=>{}
のぶん、fs.promises.rm
は .promises
のぶん若干長いためです。
fs.rm
系に再帰的削除オプションが追加されたため、fs.rmdir
系の recursive
オプションは v16.0.0 で deprecated になりました。将来的にこのオプションは指定しても無視されることになります。
[nix-shell:~/fs]$ node -v
v16.1.0
[nix-shell:~/fs]$ node -e "fs.rmdirSync('bin', {recursive: true})"
(node:11973) [DEP0147] DeprecationWarning: In future versions of Node.js, fs.rmdir(path, { recursive: true }) will be removed. Use fs.rm(path, { recursive: true }) instead
(Use `node --trace-deprecation ...` to show where the warning was created)
fs.rm
が現行 LTS すべてで使えるようになるのは Node.js v12 が EOL になる 2022-04-30 以降です。それか v12 に fs.rm
がバックポートされるかもしれません。
参考リンク
fs.rmdir
の recursive
を知ってドキュメントを見に行ったら deprecated になっててびっくりしたのがこの記事を書いたきっかけです。
Discussion