it-swarm.com.de

Wie kann ich mehrere npm-Skripts parallel ausführen?

In meinem package.json habe ich folgende zwei Skripte:

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

Ich muss diese beiden Skripts parallel jedes Mal ausführen, wenn ich in Node.js entwickle. Als erstes dachte ich daran, ein drittes Skript hinzuzufügen:

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

... aber das wartet, bis start-watch beendet ist, bevor wp-server ausgeführt wird.

Wie kann ich diese parallel ausführen? Bitte beachten Sie, dass ich die output dieser Befehle sehen muss. Wenn Ihre Lösung ein Build-Tool enthält, verwende ich lieber gulp anstelle von grunt, da ich es bereits in einem anderen Projekt verwende.

361
André Pena

Verwenden Sie ein Paket namens gleichzeitig .

npm i concurrently --save-dev

Dann richten Sie Ihre npm run dev-Aufgabe so ein:

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

Die Verwendung des Concurrently-Pakets funktioniert, aber Sie benötigen es nicht, um dies zu erreichen. Sie können einfach eine Pipe verwenden, wenn UNIX-basierte Maschinen gleichzeitig Aufgaben ausführen. Ich würde diese Methode gegenüber der anderen vorschlagen, weil Sie keine weiteren Abhängigkeiten hinzufügen müssen.

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

Wenn Sie eine UNIX-ähnliche Umgebung verwenden, verwenden Sie einfach & als Trennzeichen: 

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

Wenn Sie an einer plattformübergreifenden Lösung interessiert sind, können Sie das Modul npm-run-all verwenden:

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

Von Windows cmd können Sie start verwenden:

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

Jeder auf diese Weise gestartete Befehl beginnt in einem eigenen Fenster.

51
o.v.

Sie sollten npm-run-all (oder concurrently, parallelshell) verwenden, da sie mehr Kontrolle über Start- und Beendigungsbefehle hat. Die Operatoren &, | sind schlechte Ideen, da Sie sie nach Abschluss aller Tests manuell stoppen müssen.

Dies ist ein Beispiel für die Prüfung des Winkelmessers durch 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 = Befehle parallel ausführen.

-r = Beenden Sie alle Befehle, wenn einer von ihnen mit einem Beendigungscode von Null endet.

Wenn Sie npm run test ausführen, wird der Selenium-Treiber gestartet, der HTTP-Server (für die Bereitstellung Ihrer Dateien) und der Winkelmesser-Test gestartet. Sobald alle Tests abgeschlossen sind, werden der http-Server und der Selenium-Treiber geschlossen.

38
nir

Eine bessere Lösung ist die Verwendung von &

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

Wenn Sie das doppelte Et-Zeichen durch ein einzelnes Et-Zeichen ersetzen, werden die Skripts gleichzeitig ausgeführt. 

10
Neil Girardi

Ich habe fast alle Lösungen von oben überprüft und nur mit npm-run-all konnte ich alle Probleme lösen. Der Hauptvorteil gegenüber allen anderen Lösungen ist die Fähigkeit, Skript mit Argumenten ausführen auszuführen.

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

Hinweis run-p ist eine Abkürzung für npm-run-all --paraller.

Dadurch kann ich den Befehl mit Argumenten wie npm run test:watch -- Something ausführen.

EDIT:

Es gibt eine weitere nützliche Option 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.

Fügen Sie -r zu Ihrem npm-run-all-Skript hinzu, um alle Prozesse zu beenden, wenn der Code 0 abgeschlossen ist. Dies ist besonders nützlich, wenn Sie einen HTTP-Server und ein anderes Skript ausführen, das den Server verwendet.

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

Ich habe eine Crossplatform-Lösung ohne zusätzliche Module . Ich suchte nach etwas wie einem try catch Block, den ich sowohl in der cmd.exe als auch in der bash verwenden konnte. 

Die Lösung ist command1 || command2, die in beiden Umgebungen gleich zu funktionieren scheint. Die Lösung für das OP lautet also:

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

Dann funktioniert der einfache npm start (und npm run dev) auf allen Plattformen!

7
Entity Black
npm-run-all --parallel task1 task2

bearbeiten:

Sie müssen zuvor npm-run-all installiert haben. Überprüfen Sie auch diese Seite für andere Nutzungsszenarien.

5
noego

Schnelle Lösung

In diesem Fall würde ich die beste Wette sagen Wenn dieses Skript für ein privates Modul bestimmt ist, das nur auf * nix-basierten Maschinen ausgeführt werden soll , können Sie den Steueroperator für das Aufspalten von Prozessen verwenden. Dies sieht folgendermaßen aus: &

Ein Beispiel dafür in einer partiellen package.json-Datei:

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

Sie führen sie dann beide parallel über npm run serve-bundle aus. Sie können die Skripte so erweitern, dass die PIDs des gegabelten Prozesses in einer Datei ausgegeben werden:

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

Google etwas wie bash control operator für forking, um mehr über seine Funktionsweise zu erfahren. Ich habe auch einige weitere Informationen zur Verwendung von Unix-Techniken in folgenden Knotenprojekten bereitgestellt:

Weiterer Kontext RE: Unix Tools & Node.js

Wenn Sie nicht unter Windows arbeiten, funktionieren Unix-Tools/-Techniken oft gut, um mit Knotenscripts etwas zu erreichen, weil: 

  1. Ein Großteil von Node.js imitiert liebevoll die Unix-Prinzipien
  2. Sie sind auf * nix (inkl. OS X) und NPM verwendet sowieso eine Shell

Module für Systemaufgaben in Nodeland sind häufig auch Abstraktionen oder Annäherungen an Unix-Tools, von fs bis streams.

5
james_womack

Sie können einen & für ein parallel ausgeführtes Skript verwenden

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

Referenzlink

3

Wie wäre es mit dem Gabeln

Eine weitere Option zum Ausführen mehrerer Knotenscripts ist ein einzelnes Knotenskript, das fork viele andere ausführen kann. Gabelung wird in Node nativ unterstützt, fügt also keine Abhängigkeiten hinzu und ist plattformübergreifend.


Minimales Beispiel

Dadurch würden die Skripts nur so wie sie sind ausgeführt und davon ausgegangen, dass sie sich im Verzeichnis des übergeordneten Skripts befinden.

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

Ausführliches Beispiel

Dadurch würden die Skripts mit Argumenten ausgeführt und durch die vielen verfügbaren Optionen konfiguriert.

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

Kommunikation mit verzweigten Skripten

Das Forking bietet außerdem den zusätzlichen Vorteil, dass das übergeordnete Skript sowohl Ereignisse aus den untergeordneten untergeordneten Prozessen empfangen als auch zurücksenden kann. Ein allgemeines Beispiel ist, dass das übergeordnete Skript seine verzweigten Kinder abtötet.

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

Weitere verfügbare Ereignisse und Methoden finden Sie in der ChildProcess-Dokumentation

2
Boaz

Ich bin auf Probleme mit & und | gestoßen, die jeweils den Status und die Fehlerausgabe beenden.

Andere Lösungen möchten jede Aufgabe mit einem bestimmten Namen ausführen, wie beispielsweise npm-run-all, was nicht mein Anwendungsfall war.

Also habe ich npm-run-parallel erstellt, das npm-Skripts asynchron ausführt und zurückmeldet, wenn sie fertig sind.

Für Ihre Skripte wäre es also:

npm-run-parallel wp-server start-watch

2
ian

Ich benutze npm-run-all schon seit einiger Zeit, bin aber nie damit klar gekommen, weil die Ausgabe des Befehls im Watch-Modus nicht gut zusammenarbeitet. Wenn ich beispielsweise create-react-app und jest im Überwachungsmodus starte, kann ich nur die Ausgabe des letzten Befehls sehen, den ich ausgeführt habe. Also habe ich die meiste Zeit alle meine Befehle manuell ausgeführt ...

Deshalb implementiere ich meine eigene lib, run-screen . Es ist noch ein sehr junges Projekt (von gestern: p), aber es könnte schlimmer sein, es anzuschauen, in deinem Fall wäre es:

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

Drücken Sie dann die Zifferntaste 1, um die Ausgabe von wp-server anzuzeigen, und drücken Sie 0, um die Ausgabe von start-watch anzuzeigen.

1
Alexandre

In meinem Fall habe ich zwei Projekte, eines warUIund das andere warAPI, und beide haben ein eigenes Skript in ihren jeweiligen package.json-Dateien.

Also, hier ist was ich getan habe.

npm run --prefix react start&  npm run --prefix express start&
0
Vikash Mishra

Einfaches Knotenskript, mit dem Sie ohne großen Aufwand loslegen können. Verwenden Sie readline, um Ausgaben zu kombinieren, damit die Zeilen nicht verstümmelt werden.

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);
});
0
Piittis