여러 개의 npm 스크립트를 병렬로 실행하려면 어떻게해야합니까?


542

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.

이것들을 어떻게 병렬로 실행할 수 있습니까? output이러한 명령 을 확인해야 합니다. 또한 솔루션에 빌드 도구가 포함 된 경우 다른 프로젝트에서 이미 사용하고 있기 때문에 gulp대신 사용하고 싶습니다 grunt.


23
&&스크립트를 실행 순차적 동안 &그들을 실행됩니다 병렬 .
vsync

그것을하는 빠른 방법은입니다 npm run start-watch & npm run wp-server. 첫 번째 명령이 백그라운드 스레드로 실행됩니다. 이것은 명령 중 하나가 오래 실행되지 않아 나중에 수동으로 종료 할 필요가 없을 때 효과적입니다. 같은 뭔가 concurrently당신이 CTRL-C와 동시에 모든 스레드를 중단 할 수 있도록 허용합니다.
Joshua Pinter

답변:


616

라는 패키지를 사용하여 동시에를 .

npm i concurrently --save-dev

그런 다음 npm run dev작업을 다음 과 같이 설정하십시오 .

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

11
node ./node_modules/concurrently/src/main.js필요하지 않습니다. concurrent모듈이 bin을./node_modules/.bin/concurrent
raine

14
도 있습니다 parallelshell은 . 실제로 concurrently콘솔 출력을 엉망 으로 하는 여러 스트림을 사용하는 것이 좋습니다 (색상이 이상하고 커서가 사라질 수 있음).하지만 그 문제parallelshell 는 없습니다 .
Stijn de Witt

3
@StijndeWitt가 동시에 언급 한 버그가 2.0.0 릴리스 에서 수정 되었습니다 . --raw출력에서 색상을 유지하기 위해 모드를 사용할 수 있습니다 .
Kimmo

23
@StijndeWitt parallelshell는 NPM - 실행 - 모든 찬성에서 사용되지 github.com/keithamus/...
jtzero

12
Javascript 빌드 / 실행 스크립트를 관리하는 더 좋은 방법이 있어야합니다. 이 플랫폼의 모든 것이 하나로 묶여있는 것 같습니다. 이스케이프 된 따옴표와 npm 빌드는 다른 'npm run'빌드를 호출하기 위해 따옴표를 사용합니다. 이것은 상당히 고통 스럽습니다.
앤드류 T 피넬

141

UNIX와 유사한 환경을 사용 &하는 경우 구분 기호로 사용 하십시오.

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

그렇지 않으면 크로스 플랫폼 솔루션에 관심이 있다면 npm-run-all 모듈을 사용할 수 있습니다 .

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

14
나는 이것을한다-때때로 내가 "ctrl-c"npm 일 때, 명령은 백그라운드에서 계속 걸려있다. 어떤 아이디어?
Kamil Tomšík 2016 년

13
a && b성공적으로 완료된 b후 시작 a되지만 nodemon은 오류없이 중지되지 않으므로 작동하지 않습니다. a & b시작 a하고 백그라운드로 이동 한 다음 b바로 시작합니다 . 승리! a | bstdout을 astdin에 파이프하여 b동시에 실행해야합니다. 원하는 효과가있을 수 있지만 여기서는 사용하지 마십시오.
j2L4e

8
@ KamilTomšík &은 프로세스를 분리하므로 정말 나쁜 생각입니다. 그것은 npm더 이상 부모 프로세스가되지 않을 것임을 의미합니다 . 당신은 npm run start-watch로 죽이지 않는 좀비로 끝날 것입니다 ctrl-c.
ngryman

6
wait교수형 프로세스와 관련된 문제를 완화하기 위해 추가하십시오 ."dev": "npm run start-watch & npm run wp-server & wait"
Ruslan Prokopchuk

2
좀비가 아닙니다. 그러나 &유닉스에서는 명령이 Cc / Cz에 응답하지 못하게하고 실패시 리턴 코드가 전파되는 것을 방지합니다.
binki

77

Windows cmd에서 다음을 사용할 수 있습니다 start.

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

이 방법으로 시작된 모든 명령은 자체 창에서 시작됩니다.


2
완벽한 솔루션! 나는 그것이 새로운 창을 시작하는 것을 좋아합니다. VS2015 package.json 요구에 적합
TetraDev

13
&&두 번째 명령을 시작하기 전에 첫 번째 명령이 완료되기를 기다리는 동안 감시자 작업이 완료되지 않기 때문에 감시자 작업이있는 경우에는 작동하지 않습니다 .
Benny Neugebauer

2
@BennyNeugebauer 명령 앞에는 "start"명령이 추가되어 각 명령에 대한 새 명령 줄이 열립니다. "&& 연산자를 사용하면 작동하지 않는다"고 생각했기 때문에 처음에는 혼란 스러웠습니다. 이 솔루션은 매우 간단하며 개발자의 추가 패키지 / 작업이 필요하지 않습니다.
Addison

5
이것은 잘못이다. 명령이 순차적으로 실행됩니다. Windows에서는 명령을 동시에 실행하려면 플러그인을 사용해야합니다.
zhekaus

1
이 Windows에만 해당되지 않습니까?
binki

62

당신은 사용해야 NPM - 실행 - 모든 (또는 concurrently, parallelshell그것을 시작하고 명령을 죽이고보다 효율적으로 제어 할 수 있기 때문에). 연산자는 &, |모든 테스트 완료 후 수동으로 중지해야하기 때문에 나쁜 아이디어이다.

다음은 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 = 명령을 병렬로 실행합니다.

-r = 명령 중 하나가 종료 코드 0으로 끝나면 모든 명령을 종료하십시오.

실행 npm run test하면 Selenium 드라이버가 시작되고 http 서버 (파일 제공)가 시작되고 각도기 테스트가 실행됩니다. 모든 테스트가 완료되면 http 서버와 셀레늄 드라이버가 닫힙니다.


3
그래도 이것이 테스트 실행에 어떻게 제대로 작동하는지 궁금합니다. webdriver-start와 http-server는 병렬로 실행될 수 있지만 각도기 작업은 처음 두 개 이후에만 실행해야합니다.
asenovm

순서에 의존 작업 @asenovm, 왜 그냥 사용하지 gulpgulp-sync?
r3wt

30

&병렬 실행 스크립트로 사용할 수 있습니다

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

참조 링크


이것은 Windows에서도 작동합니까? 죄송합니다. 노드를 처음 접했고이를 확인하는 방법을 모르겠습니다!
베니 슨 샘

@BenisonSam no, Mac에서는 작동하지만
shanehoban

25

더 나은 해결책은 사용하는 것입니다 &

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

54
아니요, 모든 플랫폼에서 작동하지 않기 때문에 좋지 않습니다.
Stijn de Witt

난 몰랐어. 어떤 플랫폼에서 작동하지 않습니까? @Corey-inter-op에 대한 경고로 답변을 업데이트하면
투표하겠습니다.

8
&Windows에서는 작동하지만 다르게 작동합니다. OSX에서는 두 명령을 동시에 실행하지만 Windows에서는 첫 번째 명령을 실행하고 첫 번째 명령이 존재하면 두 번째 명령을 실행합니다.
Trevor

3
아닙니다. 프로세스가 분리되지 않으므로 간단한 방식으로 프로세스를 종료 할 수 없습니다.
ngryman

2
@ngryman 저도 그렇게 기대했습니다. 그러나 나는 이것을 시도했고 Ctrl + C를 누르면 세 가지 프로세스 (dev, start-watch 및 wp-server)를 모두 종료합니다.
musicin3d

17

위의 거의 모든 솔루션을 확인했으며 npm-run-all로 만 모든 문제를 해결할 수있었습니다. 다른 모든 솔루션에 비해 주요 장점은 인수를 사용 하여 스크립트실행할 수 있다는 것 입니다.

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

메모 run-p는 바로 가기입니다npm-run-all --parallel

이를 통해와 같은 인수로 명령을 실행할 수 있습니다 npm run test:watch -- Something.

편집하다:

하나 더 유용이 옵션 에 대한이 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.

추가 -r사용자에 npm-run-all하나의 코드를 완료 할 때 모든 프로세스를 종료하는 스크립트 0. HTTP 서버와 서버를 사용하는 다른 스크립트를 실행할 때 특히 유용합니다.

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

15

나는이 추가 모듈없이 크로스 플랫폼 솔루션을 . cmd.exe와 bash에서 모두 사용할 수있는 try catch 블록과 같은 것을 찾고있었습니다.

해결책은 command1 || command2두 환경에서 동일하게 작동하는 것 같습니다. 따라서 OP의 솔루션은 다음과 같습니다.

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

그런 다음 모든 플랫폼에서 간단 npm start하고 npm run dev작동합니다!


11

이중 앰퍼샌드를 단일 앰퍼샌드로 바꾸면 스크립트가 동시에 실행됩니다.


정확하게, 그것은 간단하고 우아하며 종속성이나 다른 마술이 필요하지 않습니다.
magikMaker

1
@Ginzburg 다른 플랫폼에서 볼 수 있듯이 모든 플랫폼에서 동일하게 작동하지 않기 때문입니다.
Jorge Fuentes González '12

6

빠른 솔루션

이 경우, 가장 좋은 방법 은이 스크립트가 * 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",

bash 제어 연산자 와 같은 Google 은 작동 방식에 대해 더 많이 배우고 있습니다. 또한 아래 노드 프로젝트에서 유닉스 기술을 활용하는 것과 관련된 추가 컨텍스트를 제공했습니다.

추가 컨텍스트 RE : Unix Tools & Node.js

Windows를 사용하지 않는 경우 Unix 도구 / 기술은 종종 다음과 같은 이유로 노드 스크립트로 무언가를 달성하는 데 효과적입니다.

  1. Node.js의 많은 부분이 유닉스 원칙을 사랑스럽게 모방
  2. * nix (OS X 포함)에 있고 NPM이 어쨌든 셸을 사용하고 있습니다.

Nodeland에서 시스템 작업에 대한 모듈은 종종에서 추상화 또는 유닉스 도구의 근사치이다 fsstreams.


1
아니요, &Windows 에서는 연산자가 지원되지 않습니다.
Stijn de Witt

3
@StijndeWitt 내 게시물에 "Windows가 아닌 경우 ..."라고 말합니다. 내가 작업하는 사람들 중 0 %가 세계 최대의 기술 회사 중 하나에서 Windows에서 Node를 실행합니다. 분명히 내 게시물은 여전히 ​​많은 개발자들에게 가치가 있습니다.
james_womack

2
그것은 일종의 순환적인 추론 방법이 아닌가? 이와 같은 npm 스크립트를 작성 하면 Windows가 작동하지 않기 때문에 Windows 사용할 없습니다. 따라서 아무도 Windows를 사용하지 않으므로 작동하지 않습니다. 플랫폼에 의존하는 소프트웨어를 사용하게됩니다. 이제해야 할 일이 크로스 플랫폼을 수행하기가 매우 어렵다면, 그보다 좋은 절충안이 될 수 있습니다. 그러나이 문제는 동시parallelshell 과 같은 표준 npm 스크립트로 수행 하기매우 쉽습니다 .
Stijn de Witt

2
@StijndeWitt 내 추론 중 어느 것도 원형이 아닙니다. 사실 산 추론에 대한 진술을했습니다. 우리는 노드 개발자들에게 공통적 인 기술을 게시하고 있으며, 많은 개발자들이 Linux 서버에서 빌드 및 배포합니다. 예. 사용자 스크립트 인 경우 Windows에서 작동해야하지만 대부분의 npm 스크립트는 주로 * nix 시스템에서 개발 및 배포를위한 것입니다. 언급 한 모듈과 관련하여 a) 동시에 병렬 쉘 "표준"을 호출하는 것은 엄청난 확장입니다 (NPMland에서는 하루에 최대 1500 회 다운로드가 표준과 다릅니다) .b) 병렬 프로세스를 위해 추가 소프트웨어가 필요한 경우에도 사용할 수 있습니다 꿀꺽.
james_womack

@StijndeWitt 감사합니다
james_womack


5

포크는 어떻습니까

여러 노드 스크립트를 실행하는 또 다른 옵션은 수있는 단일 노드 스크립트, 함께 포크 많은 다른 사람을. 포킹은 기본적으로 노드에서 지원되므로 종속성을 추가하지 않으며 크로스 플랫폼입니다.


최소 예

스크립트를 그대로 실행하고 부모 스크립트의 디렉토리에 있다고 가정합니다.

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

자세한 예

인수와 함께 스크립트를 실행하고 사용 가능한 많은 옵션으로 구성합니다.

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

갈래의 스크립트와 통신

Forking은 상위 스크립트가 분기 된 하위 프로세스로부터 이벤트를 수신하고 다시 보낼 수 있다는 추가 이점도 있습니다. 일반적인 예는 부모 스크립트가 갈래의 자식을 죽이는 것입니다.

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

더 많은 이벤트 및 방법은 설명서를 참조하십시오ChildProcess


3

&및 에 문제가 발생하여 |상태와 오류 발생이 각각 종료됩니다.

다른 솔루션은 내 사용 사례가 아닌 npm-run-all과 같이 주어진 이름으로 모든 작업을 실행하려고합니다.

그래서 npm 스크립트를 비동기 적으로 실행하고 완료되면 다시보고하는 npm-run-parallel 을 만들었 습니다.

따라서 스크립트의 경우 다음과 같습니다.

npm-run-parallel wp-server start-watch


2

제 경우에는 두 개의 프로젝트가 있습니다. 하나는 UI 이고 다른 하나는 API 이며 둘 다 각각의 package.json파일 에 자체 스크립트가 있습니다.

여기 내가 한 일이 있습니다.

npm run --prefix react start&  npm run --prefix express start&

당신의 솔루션처럼. 또한 UI ( node app) 및 API (하위 폴더 src의 Angular , guess is cd src/ng serve) 가 있으며 첫 번째 부분 만 작동합니다. 예를 들면 node app& cd src& ng serve.
Jeb50


1

나는 npm-run-all 을 얼마 동안 사용했지만 시계 모드에서 명령의 출력이 함께 작동하지 않기 때문에 결코 함께하지 못했습니다. 예를 들어, 시계 모드를 시작 create-react-app하고 시작 jest하면 마지막으로 실행 한 명령의 출력 만 볼 수 있습니다. 그래서 대부분의 시간에 모든 명령을 수동으로 실행했습니다 ...

이것이 내 자신의 lib, run-screen을 구현하는 이유 입니다. 그것은 여전히 ​​아주 어린 프로젝트 (어제 : p)이지만 귀하의 경우에는 다음과 같이 볼 가치가 있습니다.

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

그런 다음 숫자 키 1wp-server눌러 0출력을보고를 눌러 출력을보십시오 start-watch.


1

내 솔루션은 Windows를 사용하는 데 문제가 있었지만 Piittis와 유사합니다. 그래서 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"; // I shit you not
    }
    const myProcess = spawn(command, ["run", target]); // npm run server

    myProcess.stdout.on("data", logData);
    myProcess.stderr.on("data", logData);
}

(() => {
    runProcess("server"); // package json script
    runProcess("client");
})();

0

너무 많은 번거 로움없이 작업 할 수있는 간단한 노드 스크립트. readline을 사용하여 출력을 결합하여 라인이 엉망이되지 않습니다.

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
"dev": "(cd api && start npm run start) & (cd ../client && start npm run start)"

이 작품은 창문에서

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.