複数のnpmスクリプトを並行して実行するにはどうすればよいですか?


542

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ます。


23
&&は、スクリプトを順次&実行しながら、並行して実行します。
vsync

簡単な方法はnpm run start-watch & npm run wp-serverです。これにより、最初のコマンドがバックグラウンドスレッドとして実行されます。これは、コマンドの1つが長く実行されておらず、後で手動で終了する必要がない場合に非常にうまく機能します。のようなものconcurrentlyでは、CTRL-Cを使用してすべてのスレッドを同時に強制終了できます。
Joshua Pinter

回答:


616

並行して呼び出されるパッケージを使用します。

npm i concurrently --save-dev

次に、npm run devタスクを次のように設定します。

"dev": "concurrently --kill-others \"npm run start-watch\" \"npm run wp-server\""

11
node ./node_modules/concurrently/src/main.js必要ありません。 concurrentモジュールがbinをインストールするため、スクリプトで問題なく動作します./node_modules/.bin/concurrent

14
parallelshellもあります。私は実際には、concurrentlyコンソール出力を混乱させる複数のストリームを使用することをお勧めします(色が変になり、カーソルが消える可能性があります)parallelshell、その問題はありません。
Stijn de Witt

3
@StijndeWittによって同時に言及されたバグは、2.0.0リリースで修正されました--rawモードを使用して、出力の色を保持できます。
Kimmo

23
@StijndeWitt parallelshellが非推奨になり、npm-run-allgithub.com
keithamus/

12
Javascriptビルド/実行スクリプトを管理するためのより良い方法がなければなりません。このプラットフォームのすべてが結びついているようです。エスケープされた引用符付きの引用符と、他の「npm run」ビルドを呼び出すnpmビルド..これはかなり苦痛になっています。
Andrew T Finnell 2018年

141

UNIXライクな環境を使用し&ている場合は、セパレーターとして使用するだけです。

"dev": "npm run start-watch & npm run wp-server"

それ以外の場合、クロスプラットフォームのソリューションに興味がある場合は、npm-run-all モジュールを使用できます。

"dev": "npm-run-all --parallel start-watch wp-server"

14
私はこれを行います-npmを "ctrl-c"するとき、コマンドはバックグラウンドでハングし続けます...アイデアはありますか?
KamilTomšík2016年

13
a && b正常ba終了した後に開始されますが、nodemonがエラーなしで停止することはないため、機能しません。 a & b開始a、それを背景に移動し、bすぐに開始します。勝つ!a | bstdoutのastdinを、b両方を同時に実行する必要があるstdinにパイプします。これは望ましい効果があるように見えるかもしれませんが、ここでは使用しないでください。
j2L4e 2016

8
@KamilTomšík &はプロセスを切り離すので非常に悪い考えです。つまり、それはnpm親プロセスではなくなります。npm run start-watchで殺されないゾンビになってしまいctrl-cます。
ngryman 2016

6
ただ、追加waitのプロセスをぶら下げと軽減の問題に:"dev": "npm run start-watch & npm run wp-server & wait"
ルスランProkopchuk

2
ゾンビではありません。しかし&、UNIXでは、コマンドがCc / Czに応答するのを防ぎ、また、障害が発生した場合にその戻りコードが伝搬するのを防ぎます。
binki 2018

77

あなたが使用できるwindows cmdからstart

"dev": "start npm run start-watch && start npm run wp-server"

この方法で起動されたすべてのコマンドは、独自のウィンドウで始まります。


2
完璧なソリューション!新しいウィンドウが開くのが大好きです。VS2015 package.jsonのニーズに
最適

13
これは、ウォッチャータスクがある場合は機能しません&&。2番目のコマンドを開始する前に最初のコマンドが完了するまで待機し、ウォッチャータスクが終了しないためです。
ベニー

2
@BennyNeugebauerコマンドの前には、各コマンドの新しいコマンドラインを開く「開始」コマンドがあります。「&&演算子を使用しても機能しない」と思ったので、最初も混乱しました。このソリューションは非常にシンプルで、開発者による追加のパッケージや作業は必要ありません。
Addison

5
これは間違っています。コマンドは順次実行されます。Windowsでは、コマンドを同時に実行するためにプラグインを使用する必要があります。
zhekaus

1
これはWindows固有のものではありませんか?
binki 2018

62

npm-run-all(またはconcurrentlyparallelshell)を使用する必要があります。これは、コマンドの開始と終了をより詳細に制御できるためです。事業者は&|すべてのテストが終了した後、手動で停止する必要がありますので、悪いアイデアです。

これは、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 =コマンドの1つが終了コード0で終了したときに、すべてのコマンドを強制終了します。

実行npm run testすると、Seleniumドライバが起動し、httpサーバー(ファイルを提供するため)が起動し、分度器テストが実行されます。すべてのテストが完了すると、httpサーバーとセレンドライバーが閉じます。


3
しかし、これがテストを実行するためにどのように適切に機能するのでしょうか。webdriver-startとhttp-serverは並行して実行できますが、分度器タスクは最初の2つの後にのみ実行する必要があります。
asenovm

@asenovmは、順序に依存するタスクに使用gulpgulp-syncます。
r3wt 2017

30

&並列実行スクリプトに使用できます

"dev": "npm run start-watch & npm run wp-server"

参照リンク


これはWindowsでも機能しますか?申し訳ありませんが、私はノードの初心者であり、これを確認する方法がわかりません!
ベニソンサム

@BenisonSamいいえ、Macでも動作します
shanehoban

25

より良い解決策は &

"dev": "npm run start-watch & npm run wp-server"

54
いいえ、すべてのプラットフォームで機能するわけではないので、それは良くありません。
Stijn de Witt

私はそれを知りませんでした。どのプラットフォームで動作しないのですか?@Corey-相互運用に関する警告で回答を更新し、私はあなたに賛成票を投じます
Ashley Coolman

8
&Windowsでは動作しますが、動作は異なります。OSXでは両方のコマンドを同時に実行しますが、Windowsでは最初のコマンドを実行し、最初のコマンドが存在すると、2番目のコマンドを実行します。
Trevor

3
いいえ、それはプロセスを切り離すのではなく、単純な方法でそれを強制終了することはできません。
ngryman 2016

2
@ngryman私もそう思っていました。しかし、私はこれを試しましたが、Ctrl + Cを押すと、3つのプロセス(dev、start-watch、およびwp-server)がすべて強制終了されます。
musicin3d 2017

17

私は上からほぼすべての解決策をチェックしましたが、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 --parallel

これにより、のような引数でコマンドを実行できますnpm run test:watch -- Something

編集:

1つのより有用があるオプションについてはnpm-run-all

 -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 -- {*}\" --",

15

追加のモジュールなしのクロスプラットフォームソリューションがあります。私は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)はすべてのプラットフォームで機能します!



6

迅速な解決策

この場合、最善策と言えます。 このスクリプトが* nixベースのマシンのみ実行することを目的としたプライベートモジュール用である場合は、制御演算子を使用して、次のようなforkプロセスを実行できます。&

これを部分的な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。スクリプトを拡張して、フォークされたプロセスのPIDを次のようにファイルに出力できます。

"serve-bundle": "npm run bundle & echo \"$!\" > build/bundle.pid && npm run serve & echo \"$!\" > build/serve.pid && npm run open-browser",

それがどのように機能するかについてもっと学ぶためにフォークするためのbash制御演算子のようなGoogle 。また、以下のNodeプロジェクトでUnixテクニックを活用するためのいくつかの詳細なコンテキストも提供しました。

さらなるコンテキストRE:Unix Tools&Node.js

Windowsを使用していない場合、以下の理由により、Unixツール/テクニックはNodeスクリプトで何かを達成するためによく機能します。

  1. Node.jsの多くは、愛情を込めてUnixの原則を模倣しています
  2. * nix(OS Xを含む)を使用していて、NPMがシェルを使用している

Nodelandでのシステムタスクのモジュールは、多くの場合、Unixツールの抽象化または近似で、からfsまでstreamsです。


1
いいえ、&オペレーターはWindowsではサポートされていません。
Stijn de Witt

3
@StijndeWitt私の投稿は「もしあなたがWindowsを使っていないなら...」と言っています。私が一緒に仕事をしている人の0%が、世界最大のテクノロジー企業の1つで、Windows上でNodeを実行しています。ですから、私の投稿は多くの開発者にとって依然として貴重です。
james_womack

2
循環のような推論ですね。このようにnpmスクリプトを作成すると、Windows が機能しなくなるため、Windows 使用できなくなります。したがって、誰もWindowsを使用していないため、機能しないことは問題になりません...最終的には、プラットフォームに依存するソフトウェアになります。クロスプラットフォームを実行するのが非常に難しい場合は、それよりも適切なトレードオフになる可能性があります。しかし、右ここで、この問題は、非常に簡単のような標準NPMスクリプトで行うことが並行してparallelshell
Stijn de Witt

2
@StijndeWitt私の推論はどれも循環的ではありませんでした。私は推論ではなく事実を述べた。私たちは、Node開発者に共通のテクニックを投稿しています。その多くはLinuxサーバーでビルドおよびデプロイします。はい、ユーザーランドスクリプトであればWindowsで動作するはずですが、npmスクリプトの大部分は開発とデプロイメント用であり、主に* nixマシン上で動作します。あなたが言及したモジュールに関してa)並行して「標準」の並列シェルを呼び出すことは非常に大きなストレッチです(1日あたり約1500回のダウンロードはNPMlandの標準とはかけ離れています)b)並列プロセスに追加のソフトウェアが必要な場合は、ガップ。
james_womack

@StijndeWittこれらのモジュールを知って
いただいて


5

フォークはどうですか

複数のノードスクリプトを実行するもう1つのオプションは、単一のノードスクリプトを使用することです。これにより、他の多くのスクリプトをフォークできます。フォークは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


3

私は問題に走った&|終了ステータスとエラーがそれぞれ、投げ、。

他のソリューションでは、npm-run-allなど、特定の名前のタスクを実行する必要がありますが、これは私のユースケースではありませんでした。

そこで、npmスクリプトを非同期に実行、完了したらレポートを返すnpm-run-parallelを作成しました。

したがって、スクリプトの場合は次のようになります。

npm-run-parallel wp-server start-watch


2

私の場合、2つのプロジェクトがあり、1つはUIでもう 1つはAPIで、どちらもそれぞれのpackage.jsonファイルに独自のスクリプトがあります。

だから、これが私がやったことです。

npm run --prefix react start&  npm run --prefix express start&

あなたのソリューションのように。また、持っているUInode app)とAPI(サブフォルダの角度srcが、推測ではあるcd src/ng serve)、最初の部分だけの作品。例えばnode app& cd src& ng serve
Jeb50、19年


1

私はしばらくの間npm-run-allを使用していますが、watchモードでのコマンドの出力がうまく機能しないため、うまくいきませんでした。たとえば、監視モードで起動するcreate-react-appjest、最後に実行したコマンドの出力しか表示されません。ほとんどの場合、私はすべてのコマンドを手動で実行していました...

これが、私が自分のlib run-screenを実装する理由です。それはまだ非常に若いプロジェクトです(昨日から:p)が、それを見る価値があるかもしれません、あなたの場合は次のようになります:

run-screen "npm run start-watch" "npm run wp-server"

次に、数字キー1wp-server押し0ての出力を表示し、を押しての出力を表示しますstart-watch


1

私の解決策はPiittisに似ていますが、Windowsの使用にいくつかの問題がありました。したがって、win32を検証する必要がありました。

const { spawn } = require("child_process");

function logData(data) {
    console.info(`stdout: ${data}`);
}

function runProcess(target) {
    let command = "npm";
    if (process.platform === "win32") {
        command = "npm.cmd"; // I shit you not
    }
    const myProcess = spawn(command, ["run", target]); // npm run server

    myProcess.stdout.on("data", logData);
    myProcess.stderr.on("data", logData);
}

(() => {
    runProcess("server"); // package json script
    runProcess("client");
})();

0

簡単なノードスクリプトで、面倒な作業は不要です。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);
});

0
"dev": "(cd api && start npm run start) & (cd ../client && start npm run start)"

Windowsでのこの作業

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.