javascript - Hur kan jag köra flera npm-script parallellt?
I min package.json har jag dessa två skript:
"scripts": {
"start-watch": "nodemon run-babel index.js",
"wp-server": "webpack-dev-server",
}
Jag måste köra dessa 2 skript parallellt varje gång jag börjar utveckla i Node.js. Det första jag tänkte på var att lägga till ett tredje skript så här:
"dev": "npm run start-watch && npm run wp-server"
... men det kommer att vänta på att start-watch ska slutföras innan wp-server körs.
Hur kan jag köra dessa parallellt? Tänk på att jag behöver se output från dessa kommandon. Även, om din lösning involverar ett byggverktyg, skulle jag hellre använda gulp istället för grunt eftersom jag redan använder det i ett annat projekt.
Svar #1
Använd ett paket som heter concurrently.
npm i concurrently --save-dev
Ställ sedan in din npm run dev-uppgift så här:
"dev": "concurrently --kill-others \"npm run start-watch\" \"npm run wp-server\""
Svar #2
Om du använder en UNIX-liknande miljö, använd bara & som avgränsare:
"dev": "npm run start-watch & npm run wp-server"
Annars, om du är intresserad av en plattformsoberoende lösning, kan du använda npm-run-all-modulen:
"dev": "npm-run-all --parallel start-watch wp-server"
Svar #3
Från Windows cmd kan du använda start:
"dev": "start npm run start-watch && start npm run wp-server"
Varje kommando som startas på detta sätt startar i sitt eget fönster.
Svar #4
Du bör använda npm-run-all (eller concurrently, parallelshell), eftersom det har mer kontroll över att starta och stoppa kommandon. Operatörerna &, | är dåliga idéer eftersom du måste stoppa det manuellt efter att alla tester är färdiga.
Detta är ett exempel på Protractor-testning via 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=Kör kommandon parallellt.
-r=Avsluta alla kommandon när ett av dem slutar med en utgångskod på noll.
Att köra npm run test kommer att starta Selenium-drivrutinen, starta http-servern (för att servera dina filer) och köra protractor-tester. När alla tester är färdiga stängs http-servern och Selenium-drivrutinen.
Svar #5
Jag har kontrollerat nästan alla lösningar ovan och endast med npm-run-all kunde jag lösa alla problem. Den största fördelen jämfört med alla andra lösningar är möjligheten att köra skript med argument.
{
"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",
}
Observera att
run-pär en genväg förnpm-run-all --parallel
Detta tillåter mig att köra kommando med argument som npm run test:watch -- Something.
REDIGERA:
Det finns ett alternativ till för 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.
Lägg till -r i ditt npm-run-all-skript för att avsluta alla processer när en är klar med kod 0. Detta är särskilt användbart när du kör en HTTP-server och ett annat skript som använder servern.
"test": "run-p -r test:static-server \"test:jest -- {*}\" --",
Svar #6
Jag har en plattformoberoende lösning utan några ytterligare moduler. Jag letade efter något som ett try catch-block som jag kunde använda både i cmd.exe och i bash.
Lösningen är command1 || command2 vilket verkar fungera på samma sätt i båda miljöerna. Så lösningen för OP är:
"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"
}
Då fungerar enkelt npm start (och npm run dev) på alla plattformar!
Svar #7
Använd concurrently för att köra kommandon parallellt med ett delat outputflöde. För att göra det lätt att se vilken output som kommer från vilken process, använd den förkortade kommandosyntaxen, såsom npm:wp-server. Detta gör att concurrently prefixar varje outputrad med kommandots namn.
I package.json kommer din sektion för skript att se ut så här:
"scripts": {
"start": "concurrently \"npm:start-watch\" \"npm:wp-server\"",
"start-watch": "nodemon run-babel index.js",
"wp-server": "webpack-dev-server"
}
Svar #8
Om du ersätter den dubbla och-tecknet med ett enkelt och-tecken kommer skripten att köras samtidigt.
Svar #9
Vad sägs om att forka
Ett annat alternativ för att köra flera Node-skript är med ett enda Node-skript, som kan forka många andra. Forking stöds inbyggt i Node, så det tillför inga beroenden och är plattformsoberoende.
Minimalt exempel
Detta skulle bara köra skripten som de är och anta att de finns i den överordnade skriptets katalog.
// 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));
Ordrik exempel
Detta skulle köra skripten med argument och konfigureras av de många tillgängliga alternativen.
// 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
});
Kommunicera med förgrenade skript
Forking har också den ytterligare fördelen att föräldraskriptet kan ta emot händelser från de förgrenade barnprocesserna samt skicka tillbaka. Ett vanligt exempel är att föräldraskriptet dödar sina förgrenade barn.
runningScripts.forEach(runningScript => runningScript.kill());
För fler tillgängliga händelser och metoder, se ChildProcess-dokumentationen
Svar #10
med att installera npm install concurrently
"scripts": {
"start:build": "tsc -w",
"start:run": "nodemon build/index.js",
"start": "concurrently npm:start:*"
},
