如何并行运行多个npm脚本?

时间:2022-05-23 21:34:12

In my package.json I have these two scripts:

在我的包。我有这两个脚本:

  "scripts": {
    "start-watch": "nodemon run-babel index.js",
    "wp-server": "webpack-dev-server",
  }

I have to run these 2 scripts in parallel everytime I start developing in Node.js. The first thing I thought of was adding a third script like this:

每次在Node.js中开发时,我都必须并行运行这两个脚本。我想到的第一件事是添加第三个这样的脚本:

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

... but that will wait for start-watch to finish before running wp-server.

…但是这要等到开始观察结束后才能运行wp-server。

How can I run these in parallel? Please keep in mind that I need to see the output of these commands. Also, if your solution involves a build tool, I'd rather use gulp instead of grunt because I already use it in another project.

我怎么能同时运行它们呢?请记住,我需要看到这些命令的输出。此外,如果您的解决方案涉及构建工具,我宁愿使用gulp而不是grunt,因为我已经在另一个项目中使用了它。

14 个解决方案

#1


316  

Use a package called concurrently.

使用并发调用的包。

npm i concurrently --save-dev

npm我同时——save-dev

Then setup your npm run dev task as so:

然后设置您的npm运行开发任务如下:

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

#2


206  

Using the Concurrently package works, but you do not need it to accomplish this. You can just use a pipe on UNIX based machines run concurrent tasks. I would suggest this method over the other because it saves you from having to add an additional dependency.

使用并发包可以工作,但是您不需要它来完成这个任务。您可以在基于UNIX的机器上使用管道运行并发任务。我建议您使用这种方法,因为这样可以避免添加额外的依赖项。

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

#3


65  

If you're using an UNIX-like environment, just use & as the separator:

如果您正在使用类unix环境,只需使用&作为分隔符:

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

Otherwise if you're interested on a cross-platform solution, you could use npm-run-all module:

如果您对跨平台解决方案感兴趣,可以使用npm-run-all模块:

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

#4


39  

From windows cmd you can use start:

从windows cmd你可以使用start:

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

Every command launched this way starts in its own window.

以这种方式启动的每个命令都在自己的窗口中启动。

#5


27  

You should use npm-run-all (or concurrently, parallelshell), because it has more control over starting and killing commands. The operators &, `| are bad ideas because you'll need to manually stop it after all tests are finished.

您应该使用npm-run-all(或者同时使用parallelshell),因为它对启动和终止命令有更多的控制。操作符和' |是不好的想法,因为您需要在所有测试完成之后手动停止它。

This is an example for protractor testing through npm:

这是通过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 = Run commands in parallel.

-p =并行运行命令。

-r = Kill all commands when one of them finishes with zero.

-r =当其中一个命令以0结束时杀死所有命令。

Running npm run test will start Selenium driver, start http server (to serve you files) and run protractor tests. Once all tests are finished, it will close the http server and the selenium driver.

运行npm运行测试将启动Selenium驱动程序、启动http服务器(为您提供文件)并运行量角器测试。一旦所有测试完成,它将关闭http服务器和selenium驱动程序。

#6


13  

A better solution is to use &

一个更好的解决方案是使用&。

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

#7


7  

I've checked almost all solutions from above and only with npm-run-all I was able to solve all problems. Main advantage over all other solution is an ability to run script with arguments.

我检查了上面几乎所有的解决方案,只有使用npm-run——我能够解决所有的问题。所有其他解决方案的主要优点是能够使用参数运行脚本。

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

Note run-p is shortcut for npm-run-all --paraller

注意run-p是npm-run-all - parallel的快捷方式

This allows me to run command with arguments like npm run test:watch -- Something.

这让我可以用像npm运行测试这样的参数来运行命令:观察——一些东西。

EDIT:

编辑:

There is one more useful option for npm-run-all:

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.

Add -r to your npm-run-all script to kill all processes when one finished with code 0. This is especially useful when you run a HTTP server and another script that use the server.

将-r添加到您的npm-run-all脚本中,当一个进程完成代码0时,该脚本将杀死所有进程。这在运行HTTP服务器和使用服务器的另一个脚本时特别有用。

  "test": "run-p -r test:static-server \"test:jest -- {*}\" --",

#8


6  

If you replace the double ampersand with a single ampersand, the scripts will run concurrently.

如果您用一个&符替换了双&符,脚本将同时运行。

#9


4  

Quick Solution

In this case, I'd say the best bet If this script is for a private module intended to run only on *nix-based machines, you can use the control operator for forking processes, which looks like this: &

在这种情况下,我认为最好的办法是,如果这个脚本是用于仅在基于*nix的机器上运行的私有模块,那么您可以使用控制操作符来划分进程,它看起来是这样的:&

An example of doing this in a partial package.json file:

在部分包中执行此操作的示例。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 &"
  }

You'd then execute them both in parallel via npm run serve-bundle. You can enhance the scripts to output the pids of the forked process to a file like so:

然后通过npm运行服务包并行执行它们。您可以增强脚本,将分叉过程的pid输出到如下文件:

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

Google something like bash control operator for forking to learn more on how it works. I've also provided some further context regarding leveraging Unix techniques in Node projects below:

谷歌类似bash控件操作符之类的东西,用于派生以了解它如何工作的更多信息。我还提供了一些关于在以下节点项目中利用Unix技术的进一步背景:

Further Context RE: Unix Tools & Node.js

If you're not on Windows, Unix tools/techniques often work well to achieve something with Node scripts because:

如果您没有使用Windows,那么Unix工具/技术通常可以很好地使用节点脚本实现某些功能,因为:

  1. Much of Node.js lovingly imitates Unix principles
  2. 的节点。js亲切地模仿Unix原则
  3. You're on *nix (incl. OS X) and NPM is using a shell anyway
  4. 你在*nix上(包括OS X),而NPM正在使用shell

Modules for system tasks in Nodeland are also often abstractions or approximations of Unix tools, from fs to streams.

Nodeland中的系统任务模块通常也是Unix工具的抽象或近似,从fs到流。

#10


4  

I have a crossplatform solution without any additional modules. I was looking for something like a try catch block I could use both in the cmd.exe and in the bash.

我有一个没有任何其他模块的交叉格式解决方案。我在找一个可以在cmd中同时使用的try catch块。exe和bash。

The solution is command1 || command2 which seems to work in both enviroments same. So the solution for the OP is:

解决方案是命令1 ||命令2似乎在两个环境中都适用。所以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"
}

Then simple npm start (and npm run dev) will work on all platforms!

然后简单的npm start(和npm run dev)将在所有平台上工作!

#11


2  

I ran into problems with & and |, which exit statuses and error throwing, respectively.

我遇到了&和|的问题,它们分别退出状态和抛出错误。

Other solutions want to run any task with a given name, like npm-run-all, which wasn't my use case.

其他解决方案希望运行任何给定名称的任务,比如npm-run-all,这不是我的用例。

So I created npm-run-parallel that runs npm scripts asynchronously and reports back when they're done.

因此,我创建了npm-run-parallel,它异步运行npm脚本,并在这些脚本完成后进行报告。

So, for your scripts, it'd be:

所以,对于你的剧本,应该是:

npm-run-parallel wp-server start-watch

npm-run-parallel wp-server start-watch

#12


2  

npm-run-all --parallel task1 task2

edit:

编辑:

You need to have npm-run-all installed beforehand. Also check this page for other usage scenarios.

您需要预先安装npm-run-all。还要检查此页面以了解其他使用场景。

#13


0  

How about forking

Another option to run multiple Node scripts is with a single Node script, which can fork many others. Forking is supported natively in Node, so it adds no dependencies and is cross-platform.

运行多个节点脚本的另一个选项是使用一个节点脚本,该脚本可以派生许多其他节点脚本。fork系统在Node中是原生支持的,因此它不添加依赖项,并且是跨平台的。


Minimal example

This would just run the scripts as-is and assume they're located in the parent script's directory.

这将按原样运行脚本,并假定它们位于父脚本的目录中。

// 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));

Verbose example

This would run the scripts with arguments and configured by the many available options.

这将运行带有参数的脚本,并由许多可用选项配置。

// 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
});

Communicating with forked scripts

Forking also has the added benefit that the parent script can receive events from the forked child processes as well as send back. A common example is for the parent script to kill its forked children.

Forking还有一个额外的好处,即父脚本可以接收来自forked子进程的事件,也可以接收返回的事件。一个常见的例子是父脚本杀死它的分叉子脚本。

 runningScripts.forEach(runningScript => runningScript.kill());

For more available events and methods see the ChildProcess documentation

有关更多可用的事件和方法,请参见ChildProcess文档。

#14


0  

In my case I have two projet one was UI one was API, and bother have there own script in there respective package.json.

在我的例子中,我有两个projet一个是UI一个是API,而麻烦的是有各自的脚本在各自的package.json中。

so here what I did.

这就是我所做的。

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

#1


316  

Use a package called concurrently.

使用并发调用的包。

npm i concurrently --save-dev

npm我同时——save-dev

Then setup your npm run dev task as so:

然后设置您的npm运行开发任务如下:

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

#2


206  

Using the Concurrently package works, but you do not need it to accomplish this. You can just use a pipe on UNIX based machines run concurrent tasks. I would suggest this method over the other because it saves you from having to add an additional dependency.

使用并发包可以工作,但是您不需要它来完成这个任务。您可以在基于UNIX的机器上使用管道运行并发任务。我建议您使用这种方法,因为这样可以避免添加额外的依赖项。

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

#3


65  

If you're using an UNIX-like environment, just use & as the separator:

如果您正在使用类unix环境,只需使用&作为分隔符:

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

Otherwise if you're interested on a cross-platform solution, you could use npm-run-all module:

如果您对跨平台解决方案感兴趣,可以使用npm-run-all模块:

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

#4


39  

From windows cmd you can use start:

从windows cmd你可以使用start:

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

Every command launched this way starts in its own window.

以这种方式启动的每个命令都在自己的窗口中启动。

#5


27  

You should use npm-run-all (or concurrently, parallelshell), because it has more control over starting and killing commands. The operators &, `| are bad ideas because you'll need to manually stop it after all tests are finished.

您应该使用npm-run-all(或者同时使用parallelshell),因为它对启动和终止命令有更多的控制。操作符和' |是不好的想法,因为您需要在所有测试完成之后手动停止它。

This is an example for protractor testing through npm:

这是通过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 = Run commands in parallel.

-p =并行运行命令。

-r = Kill all commands when one of them finishes with zero.

-r =当其中一个命令以0结束时杀死所有命令。

Running npm run test will start Selenium driver, start http server (to serve you files) and run protractor tests. Once all tests are finished, it will close the http server and the selenium driver.

运行npm运行测试将启动Selenium驱动程序、启动http服务器(为您提供文件)并运行量角器测试。一旦所有测试完成,它将关闭http服务器和selenium驱动程序。

#6


13  

A better solution is to use &

一个更好的解决方案是使用&。

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

#7


7  

I've checked almost all solutions from above and only with npm-run-all I was able to solve all problems. Main advantage over all other solution is an ability to run script with arguments.

我检查了上面几乎所有的解决方案,只有使用npm-run——我能够解决所有的问题。所有其他解决方案的主要优点是能够使用参数运行脚本。

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

Note run-p is shortcut for npm-run-all --paraller

注意run-p是npm-run-all - parallel的快捷方式

This allows me to run command with arguments like npm run test:watch -- Something.

这让我可以用像npm运行测试这样的参数来运行命令:观察——一些东西。

EDIT:

编辑:

There is one more useful option for npm-run-all:

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.

Add -r to your npm-run-all script to kill all processes when one finished with code 0. This is especially useful when you run a HTTP server and another script that use the server.

将-r添加到您的npm-run-all脚本中,当一个进程完成代码0时,该脚本将杀死所有进程。这在运行HTTP服务器和使用服务器的另一个脚本时特别有用。

  "test": "run-p -r test:static-server \"test:jest -- {*}\" --",

#8


6  

If you replace the double ampersand with a single ampersand, the scripts will run concurrently.

如果您用一个&符替换了双&符,脚本将同时运行。

#9


4  

Quick Solution

In this case, I'd say the best bet If this script is for a private module intended to run only on *nix-based machines, you can use the control operator for forking processes, which looks like this: &

在这种情况下,我认为最好的办法是,如果这个脚本是用于仅在基于*nix的机器上运行的私有模块,那么您可以使用控制操作符来划分进程,它看起来是这样的:&

An example of doing this in a partial package.json file:

在部分包中执行此操作的示例。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 &"
  }

You'd then execute them both in parallel via npm run serve-bundle. You can enhance the scripts to output the pids of the forked process to a file like so:

然后通过npm运行服务包并行执行它们。您可以增强脚本,将分叉过程的pid输出到如下文件:

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

Google something like bash control operator for forking to learn more on how it works. I've also provided some further context regarding leveraging Unix techniques in Node projects below:

谷歌类似bash控件操作符之类的东西,用于派生以了解它如何工作的更多信息。我还提供了一些关于在以下节点项目中利用Unix技术的进一步背景:

Further Context RE: Unix Tools & Node.js

If you're not on Windows, Unix tools/techniques often work well to achieve something with Node scripts because:

如果您没有使用Windows,那么Unix工具/技术通常可以很好地使用节点脚本实现某些功能,因为:

  1. Much of Node.js lovingly imitates Unix principles
  2. 的节点。js亲切地模仿Unix原则
  3. You're on *nix (incl. OS X) and NPM is using a shell anyway
  4. 你在*nix上(包括OS X),而NPM正在使用shell

Modules for system tasks in Nodeland are also often abstractions or approximations of Unix tools, from fs to streams.

Nodeland中的系统任务模块通常也是Unix工具的抽象或近似,从fs到流。

#10


4  

I have a crossplatform solution without any additional modules. I was looking for something like a try catch block I could use both in the cmd.exe and in the bash.

我有一个没有任何其他模块的交叉格式解决方案。我在找一个可以在cmd中同时使用的try catch块。exe和bash。

The solution is command1 || command2 which seems to work in both enviroments same. So the solution for the OP is:

解决方案是命令1 ||命令2似乎在两个环境中都适用。所以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"
}

Then simple npm start (and npm run dev) will work on all platforms!

然后简单的npm start(和npm run dev)将在所有平台上工作!

#11


2  

I ran into problems with & and |, which exit statuses and error throwing, respectively.

我遇到了&和|的问题,它们分别退出状态和抛出错误。

Other solutions want to run any task with a given name, like npm-run-all, which wasn't my use case.

其他解决方案希望运行任何给定名称的任务,比如npm-run-all,这不是我的用例。

So I created npm-run-parallel that runs npm scripts asynchronously and reports back when they're done.

因此,我创建了npm-run-parallel,它异步运行npm脚本,并在这些脚本完成后进行报告。

So, for your scripts, it'd be:

所以,对于你的剧本,应该是:

npm-run-parallel wp-server start-watch

npm-run-parallel wp-server start-watch

#12


2  

npm-run-all --parallel task1 task2

edit:

编辑:

You need to have npm-run-all installed beforehand. Also check this page for other usage scenarios.

您需要预先安装npm-run-all。还要检查此页面以了解其他使用场景。

#13


0  

How about forking

Another option to run multiple Node scripts is with a single Node script, which can fork many others. Forking is supported natively in Node, so it adds no dependencies and is cross-platform.

运行多个节点脚本的另一个选项是使用一个节点脚本,该脚本可以派生许多其他节点脚本。fork系统在Node中是原生支持的,因此它不添加依赖项,并且是跨平台的。


Minimal example

This would just run the scripts as-is and assume they're located in the parent script's directory.

这将按原样运行脚本,并假定它们位于父脚本的目录中。

// 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));

Verbose example

This would run the scripts with arguments and configured by the many available options.

这将运行带有参数的脚本,并由许多可用选项配置。

// 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
});

Communicating with forked scripts

Forking also has the added benefit that the parent script can receive events from the forked child processes as well as send back. A common example is for the parent script to kill its forked children.

Forking还有一个额外的好处,即父脚本可以接收来自forked子进程的事件,也可以接收返回的事件。一个常见的例子是父脚本杀死它的分叉子脚本。

 runningScripts.forEach(runningScript => runningScript.kill());

For more available events and methods see the ChildProcess documentation

有关更多可用的事件和方法,请参见ChildProcess文档。

#14


0  

In my case I have two projet one was UI one was API, and bother have there own script in there respective package.json.

在我的例子中,我有两个projet一个是UI一个是API,而麻烦的是有各自的脚本在各自的package.json中。

so here what I did.

这就是我所做的。

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