可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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:
\"dev\": \"npm run start-watch && npm run wp-server\"
... but that will wait for start-watch
to finish before running 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.
回答1:
Use a package called concurrently.
npm i concurrently --save-dev
Then setup your npm run dev
task as so:
\"dev\": \"concurrently --kill-others \\\"npm run start-watch\\\" \\\"npm run wp-server\\\"\"
回答2:
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.
\"dev\": \"npm run start-watch | npm run wp-server\"
回答3:
If you\'re using an UNIX-like environment, just use &
as the separator:
\"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:
\"dev\": \"npm-run-all --parallel start-watch wp-server\"
回答4:
From windows cmd you can use start
:
\"dev\": \"start npm run start-watch && start npm run wp-server\"
Every command launched this way starts in its own window.
回答5:
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.
This is an example for protractor testing through 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.
-r
= Kill all commands when one of them finishes with an exit code of zero.
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.
回答6:
A better solution is to use &
\"dev\": \"npm run start-watch & npm run wp-server\"
回答7:
If you replace the double ampersand with a single ampersand, the scripts will run concurrently.
回答8:
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.
{
\"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
This allows me to run command with arguments like npm run test:watch -- Something
.
EDIT:
There is one more useful option for 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.
\"test\": \"run-p -r test:static-server \\\"test:jest -- {*}\\\" --\",
回答9:
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.
The solution is command1 || command2
which seems to work in both enviroments same. So the solution for the OP is:
\"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!
回答10:
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: &
An example of doing this in a partial package.json file:
{
\"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:
\"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:
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:
- Much of Node.js lovingly imitates Unix principles
- You\'re on *nix (incl. OS X) and NPM is using a shell anyway
Modules for system tasks in Nodeland are also often abstractions or approximations of Unix tools, from fs
to streams
.
回答11:
npm-run-all --parallel task1 task2
edit:
You need to have npm-run-all installed beforehand. Also check this page for other usage scenarios.
回答12:
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.
So I created npm-run-parallel that runs npm scripts asynchronously and reports back when they\'re done.
So, for your scripts, it\'d be:
npm-run-parallel wp-server start-watch
回答13:
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.
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.
runningScripts.forEach(runningScript => runningScript.kill());
For more available events and methods see the ChildProcess
documentation
回答14:
In my case I have two projects, one was UI and the other was API, and both have their own script in their respective package.json
files.
So, here is what I did.
npm run --prefix react start& npm run --prefix express start&