Как запустить несколько npm-скриптов параллельно?
В моем файле 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
.
Как я могу запустить эти скрипты в параллельном режиме? Имейте в виду, что я хочу видеть вывод
этих команд. Если ваше решение включает инструмент сборки, то я предпочёл бы использовать gulp
вместо grunt
, так как я уже использую его в другом проекте.
5 ответ(ов)
Вам действительно не нужно использовать дополнительные модули для кросс-платформенных решений. Вы можете воспользоваться конструкцией command1 || command2
, которая будет работать как в cmd.exe, так и в bash.
Вот пример вашего package.json
, который иллюстрирует это решение:
"scripts": {
"start-watch": "nodemon run-babel index.js",
"wp-server": "webpack-dev-server",
// первая команда предназначена для cmd.exe, вторая – для 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
, вы сможете без проблем работать на всех платформах!
Если заменить двойной амперсанд на одинарный, скрипты будут выполняться параллельно.
Для начала, убедитесь, что у вас установлен пакет concurrently
. Это можно сделать, выполнив команду:
npm install concurrently --save-dev
После этого вы можете использовать concurrently
для одновременного запуска нескольких скриптов NPM. В вашем package.json
у вас уже есть определенные скрипты:
"scripts": {
"start:build": "tsc -w",
"start:run": "nodemon build/index.js",
"start": "concurrently npm:start:*"
}
Здесь скрипт start
запускает все скрипты, начинающиеся с start:
. В вашем случае это start:build
(который будет компилировать TypeScript в режиме "watch") и start:run
(который будет запускать ваш скомпилированный файл с помощью nodemon
).
Теперь, когда вы выполните команду:
npm start
Оба скрипта запустятся одновременно: один будет следить за изменениями в ваших TypeScript файлах и компилировать их по мере необходимости, а другой будет следить за вашими изменениями в скомпилированном JavaScript файле и перезапускать сервер, если вы внесете изменения.
Таким образом, concurrently
помогает вам эффективно работать с несколькими процессами одновременно.
Быстрое решение
Если этот скрипт предназначен для частного модуля, который будет работать только на машинах с *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
. Вы также можете улучшить скрипты, чтобы выводить идентификаторы процессов (pid) вторичных процессов в файл следующим образом:
"serve-bundle": "npm run bundle & echo \"$!\" > build/bundle.pid && npm run serve & echo \"$!\" > build/serve.pid && npm run open-browser",
Ищите в Google что-то вроде bash control operator for forking, чтобы узнать больше о том, как это работает. Я также привел дополнительный контекст о том, как использовать техники Unix в проектах на Node ниже:
Дополнительный контекст о Unix-инструментах и Node.js
Если вы не на Windows, техники/инструменты Unix часто хорошо работают для решения задач с скриптами на Node, потому что:
- Многие аспекты Node.js тщательно имитируют принципы Unix.
- Вы на *nix (включая OS X), и NPM использует оболочку в любом случае.
Модули для системных задач в Nodeland тоже часто являются абстракциями или приближенными аналогами инструментов Unix, от fs
до streams
.
Мое решение похоже на решение 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"; // Я не шучу
}
const myProcess = spawn(command, ["run", target]); // npm run server
myProcess.stdout.on("data", logData);
myProcess.stderr.on("data", logData);
}
(() => {
runProcess("server"); // скрипт из package json
runProcess("client");
})();
Как видно, я добавил условие для определения платформы, чтобы правильно вызвать команду npm
на Windows, используя npm.cmd
. Это необходимо, так как на Windows обычная команда npm
может не распознаваться.
Использование async/await с циклом forEach
Запись в файлы в Node.js
Функция map для объектов (вместо массивов)
Как получить полный объект в console.log() Node.js, а не '[Object]'?
Как прочитать JSON-файл в память сервера?