私のpackage.json
には、次の2つのスクリプトがあります。
"scripts": {
"start-watch": "nodemon run-babel index.js",
"wp-server": "webpack-dev-server",
}
Node.jsで開発を始めるたびに、これら2つのスクリプト を並行して 実行する必要があります。私が最初に考えたことは、このような3番目のスクリプトを追加することでした。
"dev": "npm run start-watch && npm run wp-server"
...しかしstart-watch
を実行する前にwp-server
が終了するのを待ちます。
どうすればこれらを並列に実行できますか? これらのコマンドのoutput
を見る必要があることを覚えておいてください。また、もしあなたのソリューションがビルドツールを含んでいるのなら、私はgulp
の代わりにgrunt
を使った方がいいでしょう。なぜなら私はすでにそれを別のプロジェクトで使っているからです。
同時に というパッケージを使用してください。
npm i concurrently --save-dev
それではnpm run dev
タスクを以下のように設定してください。
"dev": "concurrently --kill-others \"npm run start-watch\" \"npm run wp-server\""
Concurrentlyパッケージを使うことはできますが、これを達成するためにそれを必要としません。あなただけのUNIXベースのマシン上でパイプを使用することができます同時タスクを実行します。他の方法よりもこの方法をお勧めします。これにより、追加の依存関係を追加する必要がなくなります。
"dev": "npm run start-watch > /dev/null | npm run wp-server"
注:最初のコマンドはその出力を無視します
UNIX風の環境を使用している場合は、&
を区切り文字として使用してください。
"dev": "npm run start-watch & npm run wp-server"
そうでなければ、クロスプラットフォームソリューションに興味があるなら、 npm-run-all moduleを使うことができます。
"dev": "npm-run-all --parallel start-watch wp-server"
Windows cmdから start
を使うことができます。
"dev": "start npm run start-watch && start npm run wp-server"
この方法で起動されたすべてのコマンドは、独自のウィンドウで始まります。
npm-run-all (またはconcurrently
、parallelshell
)を使用する必要があります。起動コマンドと強制終了コマンドを制御できるからです。演算子&
、|
は、すべてのテストが終了した後に手動で停止する必要があるため、悪い考えです。
これは、npmによる分度器テストの例です。
scripts: {
"webdriver-start": "./node_modules/protractor/bin/webdriver-manager update && ./node_modules/protractor/bin/webdriver-manager start",
"protractor": "./node_modules/protractor/bin/protractor ./tests/protractor.conf.js",
"http-server": "./node_modules/http-server/bin/http-server -a localhost -p 8000",
"test": "npm-run-all -p -r webdriver-start http-server protractor"
}
-p
=コマンドを並列に実行します。
-r
=いずれかのコマンドが終了コード0で終了したら、すべてのコマンドを終了します。
npm run test
を実行するとSeleniumドライバが起動し、httpサーバが起動し(ファイルを提供するため)、分度器テストが実行されます。すべてのテストが終了したら、httpサーバーとSeleniumドライバを閉じます。
もっと良い解決策は&
を使うことです。
"dev": "npm run start-watch & npm run wp-server"
ダブルアンパーサンドをシングルアンパーサンドに置き換えると、スクリプトは同時に実行されます。
私は上からほとんどすべての解決策をチェックし、 npm-run-all だけですべての問題を解決できました。他のすべてのソリューションに対する主な利点は、 引数を付けてスクリプトを実行 を実行できることです。
{
"test:static-server": "cross-env NODE_ENV=test node server/testsServer.js",
"test:jest": "cross-env NODE_ENV=test jest",
"test": "run-p test:static-server \"test:jest -- {*}\" --",
"test:coverage": "npm run test -- --coverage",
"test:watch": "npm run test -- --watchAll",
}
注
run-p
はnpm-run-all --paraller
のショートカットです。
これは私がnpm run test:watch -- Something
のような引数でcommandを実行することを可能にします。
編集:
npm-run-all
にもう1つ便利な option があります。
-r, --race - - - - - - - Set the flag to kill all tasks when a task
finished with zero. This option is valid only
with 'parallel' option.
-r
スクリプトにnpm-run-all
を追加して、コード0
で終了したらすべてのプロセスを強制終了します。これは、HTTPサーバーとそのサーバーを使用する別のスクリプトを実行するときに特に便利です。
"test": "run-p -r test:static-server \"test:jest -- {*}\" --",
追加のモジュールなしでクロスプラットフォームソリューションを持っています 。 cmd.exeとbashの両方で使えるtry catchブロックのようなものを探していました。
解決策はcommand1 || command2
で、どちらの環境でも同じように動作します。したがって、OPの解決策は次のとおりです。
"scripts": {
"start-watch": "nodemon run-babel index.js",
"wp-server": "webpack-dev-server",
// first command is for the cmd.exe, second one is for the bash
"dev": "(start npm run start-watch && start npm run wp-server) || (npm run start-watch & npm run wp-server)",
"start": "npm run dev"
}
そうすれば、単純なnpm start
(とnpm run dev
)はすべてのプラットフォームで動作します。
npm-run-all --parallel task1 task2
編集:
事前に npm-run-all をインストールしておく必要があります。また、 このページ その他の使用シナリオについても確認してください。
この場合、私は最善の策を言うだろう このスクリプトが* nixベースのマシンでのみ実行することを目的としたプライベートモジュール用のものである場合 、次のようにプロセスをフォークするために制御演算子を使用できます。&
部分的なpackage.jsonファイルでこれを行う例:
{
"name": "npm-scripts-forking-example",
"scripts": {
"bundle": "watchify -vd -p browserify-hmr index.js -o bundle.js",
"serve": "http-server -c 1 -a localhost",
"serve-bundle": "npm run bundle & npm run serve &"
}
あなたはそれからnpm run serve-bundle
を介してそれらの両方を並行して実行するでしょう。スクリプトを拡張して、forkしたプロセスのpidをファイルに出力することができます。
"serve-bundle": "npm run bundle & echo \"$!\" > build/bundle.pid && npm run serve & echo \"$!\" > build/serve.pid && npm run open-browser",
Googleの機能の詳細については、フォーク用bashコントロール演算子のようなものを参照してください。以下のNodeプロジェクトでUnixのテクニックを活用することに関して、さらにいくつかのコンテキストを提供しました。
Windowsを使用していないのであれば、UnixのツールやテクニックはNodeスクリプトで何かを達成するためにうまくいくことがよくあります。
Nodelandのシステムタスクのためのモジュールはまた、しばしばfs
からstreams
まで、Unixツールの抽象化または近似です。
複数のNodeスクリプトを実行するもう1つの選択肢は、単一のNodeスクリプトを使用することです。これにより、他にも多くのFORKを実行できます。分岐はNodeでネイティブにサポートされているため、依存関係は追加されず、クロスプラットフォームです。
これはスクリプトをそのまま実行し、それらが親スクリプトのディレクトリにあると仮定します。
// fork-minimal.js - run with: node fork-minimal.js
const childProcess = require('child_process');
let scripts = ['some-script.js', 'some-other-script.js'];
scripts.forEach(script => childProcess.fork(script));
これはスクリプトを引数付きで実行し、多くの利用可能なオプションによって設定されます。
// fork-verbose.js - run with: node fork-verbose.js
const childProcess = require('child_process');
let scripts = [
{
path: 'some-script.js',
args: ['-some_arg', '/some_other_arg'],
options: {cwd: './', env: {NODE_ENV: 'development'}}
},
{
path: 'some-other-script.js',
args: ['-another_arg', '/yet_other_arg'],
options: {cwd: '/some/where/else', env: {NODE_ENV: 'development'}}
}
];
let processes = [];
scripts.forEach(script => {
let runningScript = childProcess.fork(script.path, script.args, script.options);
// Optionally attach event listeners to the script
runningScript.on('close', () => console.log('Time to die...'))
runningScripts.Push(runningScript); // Keep a reference to the script for later use
});
フォークには、親スクリプトがフォークバックされた子プロセスからイベントを受信できるだけでなく、返信できるという追加の利点もあります。一般的な例は、親スクリプトがその分岐した子を殺すことです。
runningScripts.forEach(runningScript => runningScript.kill());
利用可能なイベントやメソッドについては ChildProcess
documentation を参照してください。
私は&
と|
で問題に遭遇しました。これらはそれぞれステータスとエラースローを終了します。
他の解決策は、npm-run-allのように、与えられた名前でタスクを実行したいというもので、これは私のユースケースではありませんでした。
そこで私は npm-run-parallel を作成しました。これはnpmスクリプトを非同期的に実行し、完了したら報告します。
ですから、あなたのスクリプトでは、次のようになります。
npm-run-parallel wp-server start-watch
私はしばらくの間 npm-run-all を使用してきましたが、watchモードでのコマンドの出力が一緒にうまく機能しないので、私は決してそれを使いませんでした。たとえば、create-react-app
とjest
を監視モードで起動した場合、最後に実行したコマンドからの出力しか見ることができません。そのため、ほとんどの場合、私はすべてのコマンドを手動で実行していました...
だからこそ、私は自分自身のライブラリ run-screen を実装しています。それはまだ非常に若いプロジェクト(昨日から:p)ですが、それを見るのはもっと悪いかもしれません。
run-screen "npm run start-watch" "npm run wp-server"
次に、数字キー1
を押すとwp-server
の出力が表示され、0
を押すとstart-watch
の出力が表示されます。
私の場合、2つのプロジェクトがあります。1つは _ ui _ 、もう1つは _ api _ です。どちらもそれぞれのpackage.json
ファイルに独自のスクリプトがあります。
だから、ここで私がやったことです。
npm run --prefix react start& npm run --prefix express start&
面倒な作業を省くためのシンプルなノードスクリプト。 readlineを使用して出力を結合し、行が破損しないようにします。
const { spawn } = require('child_process');
const readline = require('readline');
[
spawn('npm', ['run', 'start-watch']),
spawn('npm', ['run', 'wp-server'])
].forEach(child => {
readline.createInterface({
input: child.stdout
}).on('line', console.log);
readline.createInterface({
input: child.stderr,
}).on('line', console.log);
});