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

And*_*ena 469 javascript build node.js

在我的package.json我有这两个脚本:

  "scripts": {
    "start-watch": "nodemon run-babel index.js",
    "wp-server": "webpack-dev-server",
  }
Run Code Online (Sandbox Code Playgroud)

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

"dev": "npm run start-watch && npm run wp-server"
Run Code Online (Sandbox Code Playgroud)

......但是start-watch在运行之前会等待完成wp-server.

我怎样才能并行运行这些?请记住,我需要查看output这些命令.此外,如果您的解决方案涉及构建工具,我宁愿使用gulp而不是grunt因为我已经在另一个项目中使用它.

Nei*_*ner 543

使用一个名为concurrently的包.

npm i concurrently --save-dev

然后设置您的npm run dev任务:

"dev": "concurrently --kill-others \"npm run start-watch\" \"npm run wp-server\""
Run Code Online (Sandbox Code Playgroud)

  • @StijndeWitt parallelshell已被弃用,支持npm-run-all https://github.com/keithamus/parallelshell#currently-not-maintained-see-consolidation-of-multiple-similar-libraries (23认同)
  • 还有[parallelshell](https://www.npmjs.com/package/parallelshell).我实际上建议一个"并发"使用多个混乱控制台输出的流(颜色可能会变得奇怪,光标消失)而"parallelshell"没有[那个问题](https://github.com/kimmobrunfeldt/concurrently /问题/ 8). (14认同)
  • 不需要`node./ node_modules/concurrently/src/main.js`.`concurrent`在脚本中运行得很好,因为模块会将bin安装到`./ node_modules/.bin/concurrent` (11认同)
  • 我们必须有更好的方法来管理Javascript构建/运行脚本.这个平台的所有东西似乎都在一起.带有转义引号的引号和npm构建来调用其他'npm run'构建..这变得非常痛苦. (9认同)
  • 如果你正在运行 `npm run` 命令,你可以使用一个漂亮的速记并同时执行“npm:server”“npm:watch”“npm:electron”`。在标准输出中正确清理输出并为其添加前缀。完美。 (6认同)
  • @StijndeWitt同时提到的错误现已在[2.0.0发布]中修复(https://github.com/kimmobrunfeldt/concurrently/releases/tag/2.0.0).您可以使用`--raw`模式来保留输出中的颜色. (3认同)
  • @AndrewTFinnell 还有其他涉及外部配置文件的解决方案,例如 https://github.com/pawelgalazka/tasksfile 或在 grunt 和 gulp 之前,或者您可以构建自己的 cli 或使用您选择的框架的 cli。像并发这样的工具会获胜,因为它们很简单,并且不会混淆正在运行的命令 - 您不必查看另一个文件,您没有可能包含错误的大型 api 表层。另外,通过简单地运行“npm run”,您可以准确地看到正在运行哪些命令。您还可以以编程方式使用“并发”... (3认同)

Pat*_*ell 322

使用Concurrently包工作,但您不需要它来完成此任务.您可以在基于UNIX的计算机上使用管道来运行并发任务.我建议使用这种方法,因为它可以使您不必添加额外的依赖项.

"dev": "npm run start-watch > /dev/null | npm run wp-server"
Run Code Online (Sandbox Code Playgroud)

  • 我指出了这一点,因为在npm脚本中使用特定于平台的命令并不是一种好习惯. (84认同)
  • OP特别提到他们需要两个命令的输出......这会将第一个命令的输出重定向到第二个命令作为输入.数据*可能会被忽略并丢失给用户,最坏的情况是数据会被解释为输入(呃!)并做一些完全出乎意料的事情!出于这个原因,我投票给了这个答案! (16认同)
  • @Kimmo如果您在Windows上使用git,它将与提供的git bash一起使用.如果你在使用git的windows上进行大量开发,我强烈推荐[cmder](http://cmder.net/)或ConEmu作为默认控制台的替代品,并将其与Git Bash一起用作默认cmd. (12认同)
  • 我知道如何将unix工具添加到路径中.关键是`npm scripts`在cmd.exe中运行,所以你不能使用`&`来并行运行它们:`&`适用于Windows,但它的工作方式不同.在OSX上,它将同时运行两个命令,但在Windows上,它将运行第一个命令,并且在第一个命令存在后,它将运行第二个命令.http://stackoverflow.com/questions/30950032/how-can-i-run-multiple-npm-scripts-in-parallel/32541895?noredirect=1#comment59827282_33401809 (10认同)
  • 如果第二个命令可以从stdin读取,这将会发生奇怪的事情,并且它将隐藏第一个命令的输出. (4认同)
  • 为此使用管道是一个非常糟糕的主意。第一个命令不会有可见的输出,第二个命令可能会以错误的方式使用此输出。 (3认同)
  • @Emileb nope,windows上的npm使用cmd.`npm config ls -l | grep shell` http://stackoverflow.com/a/25614832/588759 (2认同)

Dio*_*oso 106

如果您使用的是类UNIX环境,&请将其用作分隔符:

"dev": "npm run start-watch & npm run wp-server"
Run Code Online (Sandbox Code Playgroud)

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

"dev": "npm-run-all --parallel start-watch wp-server"
Run Code Online (Sandbox Code Playgroud)

  • 我这样做 - 不时我"ctrl-c"npm,命令一直挂在后台......任何想法? (14认同)
  • `a && b`在`a`成功完成后启动`b`,但是nodemon永远不会没有错误地停止,因此无法工作.`a&b`开始`a`,将它移动到背景并立即启动`b`.赢得!`a | b`将`a`的stdout传递给'b`的stdin,这需要同时运行.虽然这似乎有所期望的效果,但您不应在此处使用它. (10认同)
  • 只需添加`wait`来缓解挂起进程的问题:``dev':"npm run start-watch&npm run wp-server&wait"` (5认同)
  • @KamilTomšík`&`是一个非常糟糕的主意,因为它分离了这个过程.这意味着`npm`将不再是父进程.你最终会得到一个不会被`ctrl-c`杀死的僵尸`npm run start-watch`. (4认同)
  • 否决这一点,因为 daemonize 不是运行多个命令的最佳方式。 (3认同)
  • 我认为 npm-run-all 是一个更好的解决方案,如果您正在开发公共库或某些情况,例如同时运行 babel watch 和 webpack watch 并保留控制台中显示的日志。 (3认同)
  • 这不是一个僵尸.但是unix上的`&`会阻止命令响应Cc/Cz,并且还会阻止其返回代码在发生故障时传播. (2认同)

o.v*_*.v. 69

从windows cmd你可以使用start:

"dev": "start npm run start-watch && start npm run wp-server"
Run Code Online (Sandbox Code Playgroud)

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

  • 如果你有观察者任务,这不起作用,因为`&&`在开始第二个命令之前等待第一个命令完成,观察者任务永远不会完成. (10认同)
  • 这是错的.命令将按顺序运行.在Windows上,您必须使用插件才能同时运行命令. (5认同)
  • 它现在也意味着我必须在您的项目上使用 Windows 工作。 (4认同)
  • 这不是特定于 Windows 的吗? (3认同)
  • 完美解决方案 我喜欢它启动新窗口.非常适合VS2015 package.json需要 (2认同)
  • @BennyNeugebauer命令前面有"start"命令,它为每个命令打开一个新的命令行.起初我也很困惑因为我认为"使用&&运算符不起作用".该解决方案非常简单,不需要开发人员提供额外的包/工作. (2认同)

小智 54

您应该使用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"
}
Run Code Online (Sandbox Code Playgroud)

-p =并行运行命令.

-r =当其中一个命令以退出代码零结束时,终止所有命令.

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

  • 我想知道这对于运行测试是如何正常工作的.虽然webdriver-start和http-server可以并行运行,但量角器任务应该只在前两个之后运行. (3认同)

Cor*_*rey 24

更好的解决方案是使用 &

"dev": "npm run start-watch & npm run wp-server"
Run Code Online (Sandbox Code Playgroud)

  • 不,它不是更好,因为它不适用于所有平台. (47认同)
  • `&`适用于Windows,但它的工作方式不同.在OSX上,它将同时运行两个命令,但在Windows上,它将运行第一个命令,并且在第一个命令存在后,它将运行第二个命令. (8认同)
  • 不,不是因为它分离了这个过程,你将无法以简单的方式杀死它. (3认同)
  • @ngryman这也是我所期望的。但是,我尝试了此操作,当您按Ctrl + C时,它确实杀死了所有三个进程(开发,启动监视和wp服务器)。 (2认同)

Beh*_*adi 16

您可以使用一个&并行运行脚本

"dev": "npm run start-watch & npm run wp-server"
Run Code Online (Sandbox Code Playgroud)

参考链接

  • @BenisonSam 我在我的 Windows 电脑上尝试过,即使使用单个“&”,它也不会运行第二个命令 (6认同)
  • 这也适用于 Windows 吗?抱歉,我对节点还很陌生,我不知道如何验证这一点! (2认同)

Ent*_*ack 15

我有一个没有任何附加模块跨平台解决方案.我正在寻找类似try catch块的东西,我可以在cmd.exe和bash中使用它们.

解决方案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"
}
Run Code Online (Sandbox Code Playgroud)

那么简单npm start(和npm run dev)将适用于所有平台!

  • 双“||”似乎在我的 Windows 10 PowerShell 上不起作用,但是,即使在 PowerShell 上,单个“|”似乎也能正常工作。我只用两个命令尝试过,只能看到第二部分的输出,而看不到第一部分的输出。 (2认同)

Edw*_*rey 14

使用并发可与共享输出流并行运行命令。为了方便区分哪个输出来自哪个进程,请使用缩短的命令形式,例如npm:wp-server. 这会导致同时为每个输出行添加其命令名称前缀。

在 中package.json,您的脚本部分将如下所示:

 "scripts": {
    "start": "concurrently \"npm:start-watch\" \"npm:wp-server\"",
    "start-watch": "nodemon run-babel index.js",
    "wp-server": "webpack-dev-server"
  }
Run Code Online (Sandbox Code Playgroud)


Dar*_*wic 12

我已经检查了几乎所有上面的解决方案,只有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 Code Online (Sandbox Code Playgroud)

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

这允许我使用像这样的参数运行命令npm run test:watch -- Something.

编辑:

还有一个有用的选项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.
Run Code Online (Sandbox Code Playgroud)

添加-r到您的npm-run-all脚本以在完成代码时终止所有进程0.当您运行HTTP服务器和使用该服务器的另一个脚本时,这尤其有用.

  "test": "run-p -r test:static-server \"test:jest -- {*}\" --",
Run Code Online (Sandbox Code Playgroud)


Nei*_*rdi 11

如果用单个&符号替换双和号,则脚本将同时运行.

  • @Ginzburg 因为并非对所有平台都一样,就像您在其他答案中看到的那样。 (3认同)

Yil*_*maz 11

随着安装npm install concurrently

"scripts": {
    "start:build": "tsc -w",
    "start:run": "nodemon build/index.js",
    "start": "concurrently  npm:start:*"
  },
Run Code Online (Sandbox Code Playgroud)


Boa*_*oaz 7

分叉怎么样

运行多个 Node 脚本的另一种选择是使用单个 Node 脚本,它可以派生许多其他脚本。在 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));
Run Code Online (Sandbox Code Playgroud)

详细示例

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

// 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 runningScripts= [];

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
});
Run Code Online (Sandbox Code Playgroud)

与分叉脚本通信

分叉还有一个额外的好处,即父脚本可以从分叉的子进程接收事件以及发回。一个常见的例子是父脚本杀死其分叉的孩子。

 runningScripts.forEach(runningScript => runningScript.kill());
Run Code Online (Sandbox Code Playgroud)

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


jam*_*ack 6

快速解决方案

在这种情况下,我想说最好的选择 如果这个脚本是针对仅在基于*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 &"
  }
Run Code Online (Sandbox Code Playgroud)

然后你可以通过并行执行它们npm run serve-bundle.您可以增强脚本以将分叉进程的pids输出到如下文件:

"serve-bundle": "npm run bundle & echo \"$!\" > build/bundle.pid && npm run serve & echo \"$!\" > build/serve.pid && npm run open-browser",
Run Code Online (Sandbox Code Playgroud)

Google就像bash控制运算符一样,可以分析它如何运作.我还提供了一些关于在以下Node项目中利用Unix技术的进一步背景:

进一步的上下文RE:Unix Tools&Node.js

如果您不在Windows上,Unix工具/技术通常可以很好地实现Node脚本,因为:

  1. 很多Node.js都非常喜欢Unix原理
  2. 您正在使用*nix(包括OS X),NPM正在使用shell

在Nodeland系统任务模块也往往抽象或Unix工具近似,从fsstreams.

  • @StijndeWitt我的帖子说"如果你不在Windows上......".我在世界上最大的科技公司之一工作的0%的人在Windows上运行Node.很明显,我的帖子对许多开发者来说仍然很有价值 (3认同)
  • 这是一种循环的推理方式不是吗?如果您编写这样的npm脚本,您将无法*使用Windows,因为它不起作用.所以没有人使用Windows,所以它不起作用并不重要...你最终得到平台相关的软件.现在,如果需要做的事情很难跨平台,那么这可能是一个很好的权衡.但是这里的问题很简单*与标准的npm脚本有关,例如[并发](https://www.npmjs.com/package/concurrently)和[parallelshell](https://www.npmjs.com /包/ parallelshell). (2认同)
  • @StijndeWitt我的推理都不是循环的.我做了一个事实没有推理的陈述.我们发布了Node开发人员常用的技术,其中许多人在Linux服务器上构建和部署.是的,它应该在Windows上工作,如果它是用户态脚本,但大多数npm脚本用于开发和部署 - 主要是在*nix机器上.关于你提到的模块a)同时调用并且并行"标准"(每天约1500次下载远远不是NPMland的标准)和b)如果你需要额外的软件用于并行处理,你可能会使用咕嘟咕嘟. (2认同)

noe*_*ego 6

npm-run-all --parallel task1 task2
Run Code Online (Sandbox Code Playgroud)

编辑:

您需要预先安装npm-run-all.另请查看此页面了解其他使用方案.


Muz*_*301 6

使用 npm 运行多个并行脚本的分步指南。全局安装npm-run-all包

npm i -g npm-run-all
Run Code Online (Sandbox Code Playgroud)

现在安装此包并将其保存在package.json所在的项目中

npm i npm-run-all --save-dev
Run Code Online (Sandbox Code Playgroud)

现在以这种方式修改package.json文件中的脚本

"scripts": {
    "server": "live-server index.html",
    "watch": "node-sass scss/style.scss --watch",
    "all": "npm-run-all --parallel server watch"
},
Run Code Online (Sandbox Code Playgroud)

现在运行这个命令

npm run all
Run Code Online (Sandbox Code Playgroud)

有关此包的更多详细信息,请参见给定链接 npm-run-all