web-dev-qa-db-ja.com

複数のnpmスクリプトを並列に実行する方法

私の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を使った方がいいでしょう。なぜなら私はすでにそれを別のプロジェクトで使っているからです。

397
André Pena

同時に というパッケージを使用してください。

npm i concurrently --save-dev

それではnpm run devタスクを以下のように設定してください。

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

Concurrentlyパッケージを使うことはできますが、これを達成するためにそれを必要としません。あなただけのUNIXベースのマシン上でパイプを使用することができます同時タスクを実行します。他の方法よりもこの方法をお勧めします。これにより、追加の依存関係を追加する必要がなくなります。

"dev": "npm run start-watch > /dev/null | npm run wp-server"

注:最初のコマンドはその出力を無視します

296

UNIX風の環境を使用している場合は、&を区切り文字として使用してください。

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

そうでなければ、クロスプラットフォームソリューションに興味があるなら、 npm-run-all moduleを使うことができます。

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

Windows cmdから start を使うことができます。

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

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

56
o.v.

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 =いずれかのコマンドが終了コード0で終了したら、すべてのコマンドを終了します。

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

45
nir

もっと良い解決策は&を使うことです。

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

ダブルアンパーサンドをシングルアンパーサンドに置き換えると、スクリプトは同時に実行されます。

11
Neil Girardi

私は上からほとんどすべての解決策をチェックし、 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-pnpm-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 -- {*}\" --",
10
Darkowic

追加のモジュールなしでクロスプラットフォームソリューションを持っています 。 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)はすべてのプラットフォームで動作します。

9
Entity Black

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

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

参照リンク

9
npm-run-all --parallel task1 task2

編集:

事前に npm-run-all をインストールしておく必要があります。また、 このページ その他の使用シナリオについても確認してください。

6
noego

クイックソリューション

この場合、私は最善の策を言うだろう このスクリプトが* 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のテクニックを活用することに関して、さらにいくつかのコンテキストを提供しました。

さらなる状況RE:UnixツールとNode.js

Windowsを使用していないのであれば、UnixのツールやテクニックはNodeスクリプトで何かを達成するためにうまくいくことがよくあります。

  1. Node.jsの多くはUnixの原則を愛情を込めて模倣しています
  2. あなたは* nix(OS Xを含む)を使い、NPMはとにかくシェルを使っています

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

6
james_womack

フォークはどうですか

複数の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 を参照してください。

3
Boaz

私は&|で問題に遭遇しました。これらはそれぞれステータスとエラースローを終了します。

他の解決策は、npm-run-allのように、与えられた名前でタスクを実行したいというもので、これは私のユースケースではありませんでした。

そこで私は npm-run-parallel を作成しました。これはnpmスクリプトを非同期的に実行し、完了したら報告します。

ですから、あなたのスクリプトでは、次のようになります。

npm-run-parallel wp-server start-watch

3
ian

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

だからこそ、私は自分自身のライブラリ run-screen を実装しています。それはまだ非常に若いプロジェクト(昨日から:p)ですが、それを見るのはもっと悪いかもしれません。

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

次に、数字キー1を押すとwp-serverの出力が表示され、0を押すとstart-watchの出力が表示されます。

1
Alexandre

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

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

npm run --prefix react start&  npm run --prefix express start&
0
Vikash Mishra

面倒な作業を省くためのシンプルなノードスクリプト。 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
Piittis