Làm thế nào tôi có thể chạy song song nhiều tập lệnh npm?


542

Trong tôi package.jsoncó hai kịch bản này:

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

Tôi phải chạy song song 2 tập lệnh này mỗi khi tôi bắt đầu phát triển trong Node.js. Điều đầu tiên tôi nghĩ đến là thêm một kịch bản thứ ba như thế này:

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

... nhưng điều đó sẽ đợi start-watchkết thúc trước khi chạy wp-server.

Làm thế nào tôi có thể chạy chúng song song? Xin lưu ý rằng tôi cần phải xem outputcác lệnh này. Ngoài ra, nếu giải pháp của bạn liên quan đến một công cụ xây dựng, tôi muốn sử dụng gulpthay gruntvì vì tôi đã sử dụng nó trong một dự án khác.


23
&&sẽ chạy các kịch bản của bạn một cách tuần tự trong khi &sẽ chạy chúng song song .
vsync

Một cách nhanh chóng để làm điều đó là npm run start-watch & npm run wp-server. Điều này sẽ chạy lệnh đầu tiên như là một chủ đề nền. Điều này hoạt động thực sự tốt khi một trong các lệnh không chạy lâu và không cần phải thoát thủ công sau đó. Một cái gì đó như concurrentlycho phép bạn tiêu diệt tất cả các luồng cùng lúc với CTRL-C.
Joshua Pinter

Câu trả lời:


616

Sử dụng một gói được gọi là đồng thời .

npm i concurrently --save-dev

Sau đó thiết lập npm run devnhiệm vụ của bạn như vậy:

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

11
node ./node_modules/concurrently/src/main.jskhông cần thiết concurrentsẽ hoạt động tốt trong các tập lệnh vì mô-đun cài đặt một thùng đến./node_modules/.bin/concurrent
raine

14
Ngoài ra còn có song song . Tôi thực sự khuyên một người concurrentlysử dụng nhiều luồng gây rối với đầu ra của bàn điều khiển (màu sắc có thể trở nên kỳ lạ, con trỏ biến mất) trong khi parallelshellkhông có vấn đề đó .
Stijn de Witt

3
Các lỗi được đề cập đồng thời bởi @StijndeWitt hiện đã được sửa trong phiên bản 2.0.0 . Bạn có thể sử dụng --rawchế độ để bảo toàn màu sắc ở đầu ra.
Kimmo

23
@StijndeWittallelshell đã không được ủng hộ cho npm-run-all github.com/keithamus/
Lỗi

12
Phải có một cách tốt hơn để chúng tôi quản lý các tập lệnh xây dựng / chạy Javascript. Tất cả mọi thứ cho nền tảng này dường như đã giải quyết cùng nhau. trích dẫn với dấu ngoặc kép thoát và các bản dựng npm để gọi các bản dựng 'npm run' khác .. Điều này đang trở nên khá đau đớn.
Andrew T Finnell

141

Nếu bạn đang sử dụng một môi trường giống như UNIX, chỉ cần sử dụng &như dấu phân cách:

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

Mặt khác, nếu bạn quan tâm đến giải pháp đa nền tảng, bạn có thể sử dụng mô-đun npm-run-all :

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

14
Tôi làm điều này - theo thời gian khi tôi "ctrl-c" npm, lệnh tiếp tục treo trên nền ... Có ý tưởng nào không?
Kamil Tomšík

13
a && bbắt đầu bsau khi akết thúc thành công, nhưng gật đầu không bao giờ dừng lại mà không có lỗi, do đó không thể làm việc. a & bbắt đầu a, di chuyển nó đến nền và bắt đầu bngay lập tức. Thắng lợi! a | bđặt ống dẫn ađến stdin trong bđó yêu cầu cả hai chạy đồng thời. Mặc dù điều này dường như có hiệu quả mong muốn, bạn không nên sử dụng nó ở đây.
j2L4e

8
@ KamilTomšík &là một ý tưởng thực sự tồi tệ vì nó làm mất quá trình. Nó có nghĩa là npmsẽ không còn là quá trình cha mẹ nữa. Bạn sẽ kết thúc với một thây ma npm run start-watchsẽ không bị giết ctrl-c.
ngryman

6
Chỉ cần thêm waitđể giảm thiểu vấn đề với các quy trình treo:"dev": "npm run start-watch & npm run wp-server & wait"
Ruslan Prokopchuk

2
Nó không phải là zombie. Nhưng &trên unix ngăn không cho lệnh phản hồi với Cc / Cz và cũng ngăn không cho mã trả về của nó lan truyền trong trường hợp bị lỗi.
binki

77

Từ windows cmd bạn có thể sử dụng start:

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

Mỗi lệnh khởi chạy theo cách này bắt đầu trong cửa sổ riêng của nó.


2
Giải pháp hoàn hảo! Tôi thích nó ra mắt cửa sổ mới. Tuyệt vời cho nhu cầu gói VS2015.json
TetraDev

13
Điều này không hoạt động nếu bạn có các nhiệm vụ theo dõi bởi vì &&chờ lệnh đầu tiên kết thúc trước khi bắt đầu lệnh thứ hai và một nhiệm vụ theo dõi sẽ không bao giờ kết thúc.
Benny Neugebauer

2
@BennyNeugebauer Các lệnh được đặt trước lệnh "start" sẽ mở ra một dòng lệnh mới cho mỗi lệnh. Lúc đầu tôi cũng bối rối vì tôi nghĩ "sử dụng toán tử && sẽ không hoạt động". Giải pháp này rất đơn giản và không yêu cầu gói / công việc bổ sung từ nhà phát triển.
Addison

5
Cái này sai. Lệnh sẽ được chạy tuần tự. Trên Windows, bạn phải sử dụng một plugin để chạy các lệnh đồng thời.
zhekaus

1
Đây không phải là Windows cụ thể?
binki

62

Bạn nên sử dụng npm-run-all (hoặc concurrently, parallelshell), vì nó có quyền kiểm soát nhiều hơn đối với các lệnh bắt đầu và tiêu diệt. Các nhà khai thác& , |là những ý tưởng tồi vì bạn sẽ cần dừng thủ công sau khi tất cả các thử nghiệm kết thúc.

Đây là một ví dụ để thử nghiệm thước đo góc qua 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 = Chạy các lệnh song song.

-r = Giết tất cả các lệnh khi một trong số chúng kết thúc với mã thoát bằng 0.

Chạy npm run testsẽ khởi động trình điều khiển Selenium, khởi động máy chủ http (để phục vụ các tệp của bạn) và chạy thử nghiệm thước đo góc. Khi tất cả các kiểm tra kết thúc, nó sẽ đóng máy chủ http và trình điều khiển selen.


3
Tôi tự hỏi làm thế nào điều này hoạt động đúng để chạy thử nghiệm, mặc dù. Trong khi webdo-start và http-server có thể chạy song song, tác vụ thước đo chỉ nên chạy sau hai lần đầu tiên.
asenovm

@asenovm cho các nhiệm vụ phụ thuộc đơn hàng, tại sao không chỉ sử dụng gulpgulp-sync?
r3wt

30

Bạn có thể sử dụng một &cho kịch bản chạy song song

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

Liên kết tham khảo


Điều này cũng sẽ hoạt động trong Windows? Xin lỗi, tôi khá mới với nút và tôi không biết cách xác minh điều này!
Benison Sam

@BenisonSam không, hoạt động trên Mac mặc dù
shanehoban

25

Một giải pháp tốt hơn là sử dụng &

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

54
Không, nó không tốt hơn vì nó không hoạt động trên tất cả các nền tảng.
Stijn de Witt

Tôi không biết điều đó. Những nền tảng nào nó không hoạt động trên? @Corey - cập nhật câu trả lời của bạn với cảnh báo trên inter-op và tôi sẽ nâng cao bạn
Ashley Coolman

8
&hoạt động trên Windows, nhưng nó hoạt động khác nhau. Trên OSX, nó sẽ chạy đồng thời cả hai lệnh, nhưng trên Windows, nó sẽ chạy lệnh đầu tiên và sau khi lệnh đầu tiên tồn tại, nó sẽ chạy lệnh thứ hai.
Trevor

3
Không, không phải vì nó làm mất quá trình, bạn sẽ không thể giết nó một cách đơn giản.
ngryman

2
@ngryman Đó cũng là điều tôi mong đợi. Tuy nhiên, tôi đã thử điều này và nó sẽ giết cả ba quá trình (dev, start-watch và wp-server) khi bạn nhấn Ctrl + C.
musicin3d

17

Tôi đã kiểm tra gần như tất cả các giải pháp từ phía trên và chỉ với npm-run-all tôi đã có thể giải quyết tất cả các vấn đề. Ưu điểm chính so với tất cả các giải pháp khác là khả năng chạy tập lệnh với các đối số .

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

Lưu ý run-plà lối tắt chonpm-run-all --parallel

Điều này cho phép tôi chạy lệnh với các đối số như npm run test:watch -- Something.

BIÊN TẬP:

Có một tùy chọn hữu ích hơn cho 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.

Thêm -rvào npm-run-alltập lệnh của bạn để giết tất cả các quy trình khi hoàn thành với mã 0. Điều này đặc biệt hữu ích khi bạn chạy máy chủ HTTP và một tập lệnh khác sử dụng máy chủ.

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

15

Tôi có một giải pháp đa nền tảng mà không cần bất kỳ mô-đun bổ sung nào . Tôi đang tìm kiếm một cái gì đó giống như một khối thử bắt tôi có thể sử dụng cả trong cmd.exe và trong bash.

Giải pháp là command1 || command2dường như hoạt động trong cả hai môi trường giống nhau. Vì vậy, giải pháp cho OP là:

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

Sau đó, đơn giản npm start(và npm run dev) sẽ hoạt động trên tất cả các nền tảng!


11

Nếu bạn thay thế ký hiệu kép bằng một ký hiệu đơn, các tập lệnh sẽ chạy đồng thời.


Chính xác, nó đơn giản và thanh lịch, không cần phụ thuộc hay phép thuật khác.
magikMaker

1
@Ginzburg Bởi vì không hoạt động giống nhau cho tất cả các nền tảng, như bạn có thể thấy trong các câu trả lời khác.
Jorge Fuentes González

6

Giải pháp nhanh

Trong trường hợp này, tôi muốn nói rằng đặt cược tốt nhất Nếu tập lệnh này dành cho một mô-đun riêng chỉ dự định chạy trên các máy dựa trên * nix , bạn có thể sử dụng toán tử điều khiển để xử lý các quy trình, giống như sau:&

Một ví dụ về việc này trong tệp pack.json một phần:

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

Sau đó, bạn sẽ thực hiện cả hai song song thông qua npm run serve-bundle. Bạn có thể nâng cao các tập lệnh để xuất các tệp của quy trình rẽ nhánh thành một tệp như sau:

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

Google một cái gì đó như toán tử bash control forking để tìm hiểu thêm về cách thức hoạt động của nó. Tôi cũng đã cung cấp thêm một số bối cảnh liên quan đến việc tận dụng các kỹ thuật Unix trong các dự án Node bên dưới:

Bối cảnh khác RE: Công cụ Unix & Node.js

Nếu bạn không ở trên Windows, các công cụ / kỹ thuật Unix thường hoạt động tốt để đạt được điều gì đó với các tập lệnh Node vì:

  1. Phần lớn Node.js bắt chước một cách đáng yêu các nguyên tắc Unix
  2. Bạn đang bật * nix (bao gồm OS X) và NPM vẫn đang sử dụng trình bao

Các mô-đun cho các tác vụ hệ thống trong Nodeland cũng thường là trừu tượng hoặc xấp xỉ các công cụ Unix, từ fsđến streams.


1
Không, vì &nhà điều hành không được hỗ trợ trên Windows.
Stijn de Witt

3
@StijndeWitt bài đăng của tôi nói "Nếu bạn không ở trên Windows ...". 0% số người tôi làm việc cùng, tại một trong những công ty công nghệ lớn nhất thế giới, chạy Node trên Windows. Vì vậy, rõ ràng bài viết của tôi vẫn còn giá trị cho nhiều nhà phát triển.
james_womack

2
Mặc dù đó là một cách suy luận vòng tròn phải không? Nếu bạn viết các tập lệnh npm như thế này, bạn sẽ không thể sử dụng Windows vì nó không hoạt động. Vì vậy, không ai sử dụng Windows, vì vậy không có vấn đề gì khi nó không hoạt động ... Bạn kết thúc với phần mềm phụ thuộc nền tảng. Bây giờ nếu điều cần làm là rất khó để thực hiện đa nền tảng, thì đó có thể là một sự đánh đổi tốt để thực hiện. Nhưng vấn đề này ở đây rất dễ thực hiện với các tập lệnh npm tiêu chuẩn như đồng thờisong song .
Stijn de Witt

2
@StijndeWitt Không có lý do nào của tôi là thông tư. Tôi đã thực hiện một tuyên bố về thực tế sans lý luận. Chúng tôi đang đăng các kỹ thuật phổ biến cho các nhà phát triển Node, nhiều người trong số họ xây dựng và triển khai trên các máy chủ Linux. Đúng, nó sẽ hoạt động trên Windows nếu đó là tập lệnh người dùng, nhưng phần lớn các tập lệnh npm dành cho phát triển và triển khai chủ yếu trên các máy * nix. Về các mô-đun mà bạn đã đề cập a) thật khó khăn để gọi đồng thời và song song là "tiêu chuẩn" (~ 1500 lượt tải xuống mỗi ngày không phải là tiêu chuẩn trong NPMland) và b) nếu bạn cần phần mềm bổ sung cho quy trình song song, bạn cũng có thể sử dụng Nuốt chửng.
james_womack

@StijndeWitt Tôi đánh giá cao việc nhận thức được các mô-đun đó mặc dù cảm ơn rất nhiều
james_womack

6
npm-run-all --parallel task1 task2

biên tập:

Bạn cần phải cài đặt npm-run-all trước đó. Ngoài ra kiểm tra trang này cho các kịch bản sử dụng khác.


5

Làm thế nào về việc rèn

Một tùy chọn khác để chạy nhiều tập lệnh Node là với một tập lệnh Node duy nhất, có thể rẽ nhánh nhiều tập lệnh khác. Forking được hỗ trợ nguyên bản trong Node, vì vậy nó không thêm phụ thuộc và là nền tảng chéo.


Ví dụ tối thiểu

Điều này sẽ chỉ chạy các kịch bản như hiện tại và giả sử chúng nằm trong thư mục của tập lệnh gốc.

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

Ví dụ dài dòng

Điều này sẽ chạy các kịch bản với các đối số và được cấu hình bởi nhiều tùy chọn có sẵn.

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

Giao tiếp với các tập lệnh rẽ nhánh

Forking cũng có thêm lợi ích là tập lệnh cha có thể nhận các sự kiện từ các tiến trình con rẽ nhánh cũng như gửi lại. Một ví dụ phổ biến là kịch bản cha mẹ giết chết những đứa trẻ ngã ba của nó.

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

Để biết thêm các sự kiện và phương pháp có sẵn, xem ChildProcesstài liệu


3

Tôi gặp vấn đề với &| , trong đó thoát trạng thái và ném lỗi, tương ứng.

Các giải pháp khác muốn chạy bất kỳ tác vụ nào với một tên cụ thể, như npm-run-all, đó không phải là trường hợp sử dụng của tôi.

Vì vậy, tôi đã tạo npm-run -allel chạy các kịch bản npm không đồng bộ và báo cáo lại khi hoàn thành.

Vì vậy, đối với các tập lệnh của bạn, nó sẽ là:

npm-run-parallel wp-server start-watch


2

Trong trường hợp của tôi, tôi có hai dự án, một dự án là UI và dự án còn lại là API và cả hai đều có tập lệnh riêng trong các package.jsontệp tương ứng .

Vì vậy, đây là những gì tôi đã làm.

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

Giống như giải pháp của bạn. Cũng có UI ( node app) và API (Angular trong src thư mục con , đoán là cd src/ng serve), chỉ phần đầu tiên hoạt động. Ví dụ node app& cd src& ng serve.
Jeb50


1

Tôi đã sử dụng npm-run-all một thời gian, nhưng tôi chưa bao giờ hòa hợp với nó, bởi vì đầu ra của lệnh trong chế độ đồng hồ không hoạt động tốt với nhau. Ví dụ, nếu tôi bắt đầu create-react-appjest ở chế độ đồng hồ, tôi sẽ chỉ có thể thấy đầu ra từ lệnh cuối cùng tôi đã chạy. Vì vậy, hầu hết thời gian, tôi đã chạy tất cả các lệnh của mình một cách thủ công ...

Đây là lý do tại sao, tôi thực hiện lib riêng, tôi chạy màn hình . Dự án vẫn còn rất trẻ (từ ngày hôm qua: p) nhưng có thể đáng để xem xét, trong trường hợp của bạn, đó sẽ là:

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

Sau đó, bạn nhấn phím số 1để xem đầu ra của wp-servervà nhấn 0để xem đầu ra của start-watch.


1

Giải pháp của tôi tương tự như Piittis ', mặc dù tôi gặp một số vấn đề khi sử dụng Windows. Vì vậy, tôi đã phải xác nhận cho 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

Tập lệnh nút đơn giản để giúp bạn đi mà không gặp quá nhiều rắc rối. Sử dụng readline để kết hợp các kết quả đầu ra để các dòng không bị sai lệch.

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

công việc này trong windows

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.