まくまくNode.jsノート
npm run のスクリプトを連続実行・並列実行する (npm-run-all)
2019-10-07

なぜ npm-run-all が必要か?

package.jsonscripts プロパティでスクリプトを定義しておくと、任意のコマンドを npm run コマンド経由で実行できるようになります(以降 NPM スクリプトと呼びます)。

しかし、デフォルトでは、複数の NPM スクリプトを連続して実行する方法(Linux の cmd1 && cmd1)や、並列に実行する方法(Linux の cmd1 & cmd2)は提供されていません。 強引に各 OS のシェルの &&& を組み合わせることでできないことはありませんが、Windows と Linux で記述方法が異なるので、OS に依存した package.json になってしまいます。

このような場合に、npm-run-all という NPM パッケージを使用すると、複数の NPM スクリプトを逐次/並列実行するスクリプトを、OS に依存しない形で記述できるようになります。

npm-run-all の使い方

npm-run-all のインストール

npm-run-all は下記のようにインストールします。

$ npm install --save-dev npm-run-all

npm-run-all コマンドは、package.jsonscripts 定義の中から呼び出して使用するので、上記のように --save-dev オプションを指定して、devDependencies の依存情報に追加するようにしましょう。

npm-run-all でシーケンシャル実行 (run-s)

run-snpm-run-all のショートカット)というコマンドを使用すると、指定した NPM スクリプトをシーケンシャルに(ひとつずつ順番に)実行していくことができます。

package.json 抜粋

"scripts": {
  "hello": "run-s hello:foo hello:bar",
  "hello:foo": "echo FOO",
  "hello:bar": "echo BAR"
},

上記の hello スクリプトを実行すると、hello:foohello:bar のスクリプトが順番に実行されます。

$ npm run -s hello
FOO
BAR

ちなみに、上記のように : を使ってスクリプト名を細分化しておくと、グロブでスクリプトをまとめて指定することができます。

"scripts": {
  "hello": "run-p hello:*",

npm-run-all でパラレル実行 (run-p)

run-pnpm-run-all --parallel のショートカット)というコマンドを使用すると、指定した NPM スクリプトを並列に実行することができます。

package.json 抜粋

"scripts": {
  "hello": "run-p hello:*",
  "hello:foo": "timeout /t 3 > nul & echo FOO",
  "hello:bar": "timeout /t 3 > nul & echo BAR"
},

このサンプルは、Windows の timeout コマンド(指定した秒数だけスリープ)を使用しているのであまりよくない例ですが、run-p の効果を確かめるにはこのようなスリープ&エコーが手っ取り早いです。 下記のように実行すると、hello:foohello:bar スクリプトのスリープが同時に開始されるので、FOOBAR の出力がほぼ同時に行われます。

$ npm run -s hello
FOO
BAR

hello スクリプトの中の run-p という部分を run-s に変更すると、FOO が出力された後 3 秒待ってから BAR と表示されるはずです。

2019-10-07