在我的package.json中,我有以下两个脚本:

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


每当我开始在Node.js中进行开发时,我都必须并行运行这两个脚本。我想到的第一件事是添加第三个脚本,如下所示:

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


...但是在运行start-watch之前,它将等待wp-server完成。

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

评论

&&将依次运行脚本,而&将并行运行它们。

一种快速的方法是npm run start-watch和npm run wp-server。这将第一个命令作为后台线程运行。当其中一个命令不会长时间运行并且以后不需要手动退出时,此方法非常有效。并发之类的东西使您可以使用CTRL-C同时杀死所有线程。

#1 楼

使用并发调用的软件包。

npm i concurrently --save-dev

然后将npm run dev任务设置为:

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


评论


不需要节点./node_modules/concurrently/src/main.js。并发将在脚本中正常工作,因为该模块将bin安装到./node_modules/.bin/concurrent

–雨
2015年9月11日14:07



也有并行外壳。我实际上建议同时使用多个与控制台输出混淆的流(颜色可能变得奇怪,光标消失了),而并行外壳则没有这个问题。

– Stijn de Witt
16年5月5日在21:33

@StijndeWitt同时提到的错误现已在2.0.0版本中修复。您可以使用--raw模式保留输出中的颜色。

– Kimmo
16-02-20在15:21



@StijndeWitt parallelshell已被弃用,而推荐使用npm-run-allgithub.com/keithamus/…

– jtzero
16年6月20日在23:18

我们必须有更好的方法来管理Javascript构建/运行脚本。该平台的所有内容似乎都固定在一起。带转义引号的引号和npm构建以调用其他“ npm run”构建。这变得非常痛苦。

–安德鲁(Andrew T Finnell)
18年3月21日在13:42

#2 楼

如果您使用的是类似UNIX的环境,则只需使用&作为分隔符:

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


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

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


评论


我这样做-不时“ ctrl -c” npm,该命令一直挂在后台...有什么想法吗?

–卡米尔(KamilTomšík)
16 Mar 15 '16 at 13:03

a && b在成功完成之后启动b,但是nodemon绝不会无误停止,因此无法正常工作。 a和b启动a,将其移至背景,然后立即启动b。赢得!一个| b将a的stdout传送到b的stdin,这要求两者同时运行。尽管这似乎可以达到预期的效果,但是您不应该在这里使用它。

– j2L4e
16年6月6日13:00

@KamilTomšík&是一个非常糟糕的主意,因为它使过程分离。这意味着npm将不再是父进程。您将得到一个不会被ctrl-c杀死的僵尸npm run启动手表。

–ngryman
16 Dec 31'在10:25



只需添加等待以缓解挂起进程的问题:“ dev”:“ npm run start-watch&npm run wp-server&wait”

–俄罗斯Prokopchuk
17年1月25日在7:14

这不是僵尸。但是&on unix可以防止命令对C-c / C-z作出响应,并且还可以防止在失败的情况下传播其返回代码。

– Binki
18年8月5日在18:22

#3 楼

在Windows cmd中,您可以使用start

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


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

评论


如果您有观察者任务,则此方法不起作用,因为&&在启动第二个命令之前等待第一个命令完成,并且观察者任务将永远不会完成。

– Benny Neugebauer
17年5月15日在15:02

@BennyNeugebauer命令之前带有“开始”命令,该命令为每个命令打开新的命令行。一开始我也很困惑,因为我认为“使用&&运算符将不起作用”。该解决方案非常简单,不需要开发人员提供额外的软件包/工作。

–艾迪生
17年8月9日在12:52



错了命令将按顺序运行。在Windows上,必须使用插件才能同时运行命令。

– zhekaus
17年11月21日在12:19

这不是特定于Windows的吗?

– Binki
18年8月5日在18:23

这也意味着我必须在您的项目上使用Windows。

– airtonix
'18 Sep 9'在2:18

#4 楼

您应该使用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 =当其中一个命令的退出代码为零时终止所有命令。

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

评论


我不知道这如何正常运行测试。虽然webdriver-start和http-server可以并行运行,但量角器任务仅应在前两个之后运行。

–asenovm
16 Dec 16'在11:26

@asenovm用于执行与订单有关的任务,为什么不只使用gulp和gulp-sync?

– r3wt
17年8月3日在21:47

#5 楼

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

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


参考链接

评论


在Windows中也可以使用吗?抱歉,我是Node的新手,我不知道该如何验证!

– Benison Sam
1月14日15:03

我在Windows PC上尝试过的@BenisonSam,即使使用单个“&”,它也不会运行第二个命令

– Franva
8月24日23:58

#6 楼

更好的解决方案是使用&

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


评论


不,这不是更好,因为它并非在所有平台上都适用。

– Stijn de Witt
16年1月2日在21:44

我不知道。它在什么平台上不起作用? @Corey-使用互操作警告更新您的答案,我会投票给您

–阿什利·库尔曼(Ashley Coolman)
16-2-24在6:59



&可在Windows上使用,但工作方式有所不同。在OSX上,它将同时运行两个命令,但是在Windows上,它将运行第一个命令,并且在第一个命令存在后,它将运行第二个命令。

–特雷弗
16年3月18日在18:16

不,这不是因为它使流程分离,您将无法以简单的方式将其杀死。

–ngryman
16 Dec 31'在10:27

@ngryman这也是我的期望。但是,我尝试了此操作,当您按Ctrl + C时,它确实杀死了所有三个进程(开发,启动监视和wp服务器)。

–musicin3d
17年4月1日在22:00

#7 楼

我已经从上面检查了几乎所有解决方案,仅使用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 --parallel的快捷方式


这使我可以使用诸如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.


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

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


#8 楼

我有一个没有任何其他模块的跨平台解决方案。我一直在寻找可以在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 楼

如果将双“与”号替换为单个“与”号,则脚本将同时运行。

评论


确实,它简单而优雅,不需要依赖项或其他魔术。

–magikMaker
18年6月7日在9:46

@Ginzburg因为在所有平台上的工作方式都不相同,就像您在其他答案中看到的那样。

–乔治·富恩特斯·冈萨雷斯(Jorge FuentesGonzález)
18/12/18在11:37

#10 楼

快速解决方案

在这种情况下,最好的选择是如果该脚本用于仅在基于* 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并联。您可以增强脚本,以将分叉过程的pids输出到文件,如下所示:

"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 Tools和Node.js

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


许多Node.js都很好地模仿了Unix原理。
OS X)和NPM无论如何都使用shell

Nodeland中用于系统任务的模块也经常是Unix工具的抽象或近似,从fsstreams

评论


不,因为Windows不支持&运算符。

– Stijn de Witt
16年1月2日,21:45

@StijndeWitt我的帖子说“如果您不在Windows上...”。在全球最大的科技公司之一中,与我合作的人中有0%在Windows上运行Node。显然,我的帖子对许多开发人员仍然有价值。

–james_womack
16年1月4日在23:27

这是一种循环推理,不是吗?如果您这样编写npm脚本,则将无法使用Windows,因为它将无法正常工作。因此,没有人使用Windows,因此它不起作用也没关系...您最终获得了依赖于平台的软件。现在,如果需要做的事情很难跨平台完成,那么这将是一个很好的权衡。但是,使用标准npm脚本(例如并发和并行shell)非常容易解决此问题。

– Stijn de Witt
16 Jan 5 '21 at 21:27

@StijndeWitt我的推理都不是循环的。我没有事实就声明了事实。我们将发布Node开发人员常用的技术,其中许多开发人员都在Linux服务器上构建和部署。是的,如果它是一个userland脚本,它应该可以在Windows上运行,但是大多数npm脚本是用于开发和部署的-大多是在* nix机器上。关于您提到的模块,a)并发调用和并行外壳“标准”(在NPMland中每天要下载约1500次,这是一个很大的负担),并且b)如果您需要其他软件来进行并行处理,则最好使用喝了

–james_womack
16年1月7日,0:12



@StijndeWitt我非常感谢您了解这些模块,谢谢您

–james_womack
16年1月7日,0:14

#11 楼

npm-run-all --parallel task1 task2


编辑:

您需要事先安装npm-run-all。另请检查此页面以了解其他使用情况。

#12 楼

如何分叉
另一个运行多个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));


详细示例
这将运行带有参数并由许多可用选项配置的脚本。
// 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
});


与派生脚本进行通信
派生还具有额外的好处,即父脚本可以从派生的子进程接收事件并发送回去。一个常见的示例是父脚本杀死它的派生子级。
 runningScripts.forEach(runningScript => runningScript.kill());

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

#13 楼

npm install npm-run-all --save-dev


package.json:

"scripts": {
  "start-watch": "...",
  "wp-server": "...",
  "dev": "npm-run-all --parallel start-watch wp-server"
}


更多信息:https://github.com/mysticatea/npm-run-all/blob /master/docs/npm-run-all.md

#14 楼

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

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

所以我创建了npm-run-parallel,它异步运行npm脚本并在完成后报告。

因此,对于您的脚本,是:

npm-run-parallel wp-server start-watch

#15 楼

就我而言,我有两个项目,一个是UI,另一个是API,并且在各自的package.json文件中都有自己的脚本。

所以,这就是我所做的。

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


评论


喜欢你的解决方案。还具有UI(节点应用程序)和API(Angular在子文件夹src中,猜测是cd src / ng服务),只有第一部分有效。例如,节点app&cd src&ng服务。

–Jeb50
19年4月3日在4:05

#16 楼

我的解决方案类似于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");
})();


#17 楼


{
"start-express": "tsc && nodemon dist/server/server.js",
"start-react": "react-scripts start",
"start-both": "npm -p -r run start-react && -p -r npm run start-express"
}

客户端和服务器都使用typescript编写。
React app是使用具有typescript模板的create-react-app创建的,并且位于默认的src目录中。 br /> Express位于服务器目录中,入口文件为server.js
打字稿代码,并转换为js并放在dist目录中。
签出我的项目以获取更多信息:https:// github.com/nickjohngray/staticbackeditor
更新:
调用npm run dev来开始操作
{"server": "tsc-watch --onSuccess \"node ./dist/server/index.js\"",
"start-server-dev": "npm run build-server-dev && node src/server/index.js",
"client": "webpack-dev-server --mode development --devtool inline-source-map --hot",
"dev": "concurrently \"npm run build-server-dev\"  \"npm run server\" \"npm run client\""}


评论


我已经更新了我的脚本,我认为那是可行的,我在上面发布了我的更新

–尼克
8月28日4:08

npm上的-p和-r是什么?

–安雅
11月13日11:04

#18 楼

我一直在使用npm-run-all一段时间,但是我从未与之相处,因为在监视模式下命令的输出不能很好地协同工作。例如,如果我在监视模式下启动create-react-appjest,我将只能看到我运行的最后一条命令的输出。所以大多数时候,我都是手动运行所有命令...

这就是为什么我实现自己的lib运行屏幕的原因。它仍然是一个非常年轻的项目(从昨天开始:p),但是值得一看,对于您而言,它是:

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


然后按数字键1查看wp-server的输出,然后按0查看start-watch的输出。

#19 楼

在父文件夹的package.json中:

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


在Windows中可以正常工作

#20 楼

只需将此npm脚本添加到根文件夹中的package.json文件中即可。
{
  ...
  "scripts": {
    ...
    "start": "react-scripts start", // or whatever else depends on your project
    "dev": "(cd server && npm run start) & (cd ../client && npm run start)"
  }
}


#21 楼


...但是在运行wp-server之前,这将等待start-watch完成。

要正常工作,您将必须在命令上使用start。其他人已经进行了说明,但这是如何工作的,您的代码如下:

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

应该是:

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

这是要执行的操作,它将为每个命令打开一个单独的实例并同时处理它们,就您最初遇到的问题而言,这不应该是一个问题。我为什么这么说?这是因为在您仅运行1条语句(这是您的最初目标)时,这些实例都会自动打开。

#22 楼

简单的节点脚本,无需太多麻烦即可开始工作。使用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);
});