javascript - multiple - npm run js file
¿Cómo puedo ejecutar múltiples scripts npm en paralelo? (17)
En mi
package.json
tengo estos dos scripts:
"scripts": {
"start-watch": "nodemon run-babel index.js",
"wp-server": "webpack-dev-server",
}
Tengo que ejecutar estos 2 scripts en paralelo cada vez que empiezo a desarrollar en Node.js. Lo primero que pensé fue agregar un tercer script como este:
"dev": "npm run start-watch && npm run wp-server"
... pero eso esperará a que
start-watch
termine antes de ejecutar
wp-server
.
¿Cómo puedo ejecutar estos en paralelo?
Tenga en cuenta que necesito ver la
output
de estos comandos.
Además, si su solución involucra una herramienta de compilación, prefiero usar
gulp
lugar de
grunt
porque ya lo uso en otro proyecto.
¿Qué hay de bifurcación
Otra opción para ejecutar múltiples scripts de Nodo es con un solo script de Nodo, que puede fork muchos otros. La bifurcación se admite de forma nativa en Node, por lo que no agrega dependencias y es multiplataforma.
Ejemplo mínimo
Esto solo ejecutaría los scripts tal cual y supondría que están ubicados en el directorio del script principal.
// 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));
Ejemplo detallado
Esto ejecutaría los scripts con argumentos y configurados por las muchas opciones disponibles.
// 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
});
Comunicación con guiones bifurcados
Forking también tiene el beneficio adicional de que el script primario puede recibir eventos de los procesos secundarios bifurcados, así como también enviarlos de regreso. Un ejemplo común es que el script padre mate a sus hijos bifurcados.
runningScripts.forEach(runningScript => runningScript.kill());
Para más eventos y métodos disponibles, consulte la
documentación de
ChildProcess
Solución rápida
En este caso, diría que la mejor opción es que
si este script es para un módulo privado destinado a ejecutarse solo en máquinas basadas en * nix
, puede usar el operador de control para los procesos de bifurcación, que se ve así:
&
Un ejemplo de hacer esto en un archivo package.json parcial:
{
"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 &"
}
Luego los ejecutarías en paralelo a través de
npm run serve-bundle
.
Puede mejorar los scripts para generar los pids del proceso bifurcado en un archivo de esta manera:
"serve-bundle": "npm run bundle & echo /"$!/" > build/bundle.pid && npm run serve & echo /"$!/" > build/serve.pid && npm run open-browser",
Google algo así como el operador de control bash para bifurcar para aprender más sobre cómo funciona. También proporcioné un contexto adicional sobre el aprovechamiento de las técnicas de Unix en los proyectos Node a continuación:
Contexto adicional RE: Unix Tools & Node.js
Si no está en Windows, las herramientas / técnicas de Unix a menudo funcionan bien para lograr algo con los scripts de Node porque:
- Gran parte de Node.js imita amorosamente los principios de Unix
- Estás en * nix (incluido OS X) y NPM está usando un shell de todos modos
Los módulos para tareas del sistema en Nodeland también son a menudo abstracciones o aproximaciones de herramientas Unix, desde
fs
hasta
streams
.
Debe usar
npm-run-all
(o al
concurrently
,
npm-run-all
), ya que tiene más control sobre los comandos de inicio y finalización.
Los operadores
&
,
|
son malas ideas porque deberás detenerlo manualmente después de que todas las pruebas hayan terminado.
Este es un ejemplo para las pruebas de transportador a través de 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
= Ejecuta comandos en paralelo.
-r
= Mata todos los comandos cuando uno de ellos termina con un código de salida de cero.
Al ejecutar
npm run test
se iniciará el controlador Selenium, se iniciará el servidor http (para servirle los archivos) y se ejecutarán pruebas de transportador.
Una vez que todas las pruebas hayan finalizado, cerrará el servidor http y el controlador de selenio.
Desde cmd de windows puede usar
start
:
"dev": "start npm run start-watch && start npm run wp-server"
Cada comando lanzado de esta manera comienza en su propia ventana.
En mi caso, tengo dos proyectos, uno era
UI
y el otro era
API
, y ambos tienen su propio script en sus respectivos archivos
package.json
.
Entonces, esto es lo que hice.
npm run --prefix react start& npm run --prefix express start&
He comprobado casi todas las soluciones anteriores y solo con npm-run-all pude resolver todos los problemas. La principal ventaja sobre todas las demás soluciones es la capacidad de ejecutar secuencias de comandos con argumentos .
-r, --race - - - - - - - Set the flag to kill all tasks when a task
finished with zero. This option is valid only
with ''parallel'' option.
Tenga en cuenta que
run-p
es un acceso directo paranpm-run-all --paraller
Esto me permite ejecutar comandos con argumentos como
npm run test:watch -- Something
.
EDITAR:
Hay una
option
más útil para
npm-run-all
:
"test": "run-p -r test:static-server /"test:jest -- {*}/" --",
Agregue
-r
a su
npm-run-all
para eliminar todos los procesos cuando uno termine con el código
0
.
Esto es especialmente útil cuando ejecuta un servidor HTTP y otro script que usa el servidor.
"dev": "npm run start-watch & npm run wp-server"
He estado usando
npm-run-all
durante algún tiempo, pero nunca me llevé bien con él, porque la salida del comando en modo reloj no funciona bien juntos.
Por ejemplo, si inicio
create-react-app
y
jest
en modo reloj, solo podré ver el resultado del último comando que ejecuté.
Así que la mayoría de las veces, estaba ejecutando todos mis comandos manualmente ...
Por eso, implemento mi propia lib, run-screen . Todavía es un proyecto muy joven (de ayer: p) pero podría valer la pena mirarlo, en su caso sería:
run-screen "npm run start-watch" "npm run wp-server"
Luego presiona la tecla numérica
1
para ver la salida del
wp-server
y presiona
0
para ver la salida de
start-watch
.
Me encontré con problemas con
&
y
|
, que salen de los estados y arrojan errores, respectivamente.
Otras soluciones quieren ejecutar cualquier tarea con un nombre de pila, como npm-run-all, que no era mi caso de uso.
Así que creé npm-run-parallel que ejecuta scripts npm de forma asincrónica e informa cuando están listos.
Entonces, para sus guiones, sería:
npm-run-parallel wp-server start-watch
Puede usar uno
&
para secuencia de comandos de ejecución paralela
"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"
}
Script de nodo simple para que pueda comenzar sin demasiados problemas. Usando readline para combinar salidas para que las líneas no se rompan.
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);
});
Si está utilizando un entorno similar a UNIX, simplemente use
&
como separador:
"dev": "npm run start-watch & npm run wp-server"
De lo contrario, si está interesado en una solución multiplataforma, puede usar el npm-run-all :
"dev": "npm-run-all --parallel start-watch wp-server"
Si reemplaza el doble ampersand con un solo ampersand, los scripts se ejecutarán simultáneamente.
Tengo una solución de plataforma cruzada sin ningún módulo adicional . Estaba buscando algo así como un bloque try catch que podría usar tanto en cmd.exe como en bash.
La solución es
command1 || command2
command1 || command2
que parece funcionar en ambos entornos lo mismo.
Entonces la solución para el OP es:
{
"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",
}
¡Entonces
npm start
simple (y
npm run dev
) funcionarán en todas las plataformas!
Una mejor solución es usar
&
"dev": "npm run start-watch & npm run wp-server"
Usar el paquete Simultáneamente funciona, pero no lo necesita para lograrlo. Puede usar una tubería en máquinas basadas en UNIX que ejecutan tareas concurrentes. Sugeriría este método sobre el otro porque le evita tener que agregar una dependencia adicional.
"dev": "npm run start-watch > /dev/null | npm run wp-server"
nota: el primer comando tendrá su salida ignorada
Use un paquete llamado concurrently .
npm i concurrently --save-dev
Luego configure su
npm run dev
task de la siguiente manera:
"dev": "concurrently --kill-others /"npm run start-watch/" /"npm run wp-server/""
npm-run-all --parallel task1 task2
editar:
npm-run-all tener npm-run-all instalado de antemano. Consulte también option para ver otros escenarios de uso.