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

…但这将在运行wp服务器之前等待开始监视完成。

如何并行运行这些?请记住,我需要查看这些命令的输出。此外,如果您的解决方案涉及构建工具,我宁愿使用gulf而不是gulf,因为我已经在另一个项目中使用了它。


当前回答

简单的节点脚本,让您无需太多麻烦。使用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);
});

其他回答

您还可以在特定脚本上使用pre和post作为前缀。

  "scripts": {
    "predev": "nodemon run-babel index.js &",
    "dev": "webpack-dev-server"
  }

然后运行:npm运行开发

如果将双&号替换为单&号,脚本将同时运行。

如果您使用的是类似UNIX的环境,请使用&作为分隔符:

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

否则,如果您对跨平台解决方案感兴趣,可以使用npm-run-all模块:

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

由于您可能需要向该脚本中添加越来越多的内容,因此它将变得混乱且难以使用。如果您需要检查一些条件和使用的变量,该怎么办?所以我建议您看看允许使用js创建脚本的google/zx。

简单用法:

安装zx:npm i-g zx添加package.json命令(可选,您可以将所有内容移动到脚本中):

  "scripts": {
    "dev": "zx ./scripts/dev.mjs", // run script
    "build:dev": "tsc -w", // compile in watch mode
    "build": "tsc", // compile
    "start": "node dist/index.js", // run
    "start:dev": "nodemon dist/index.js", // run in watch mode
  },

创建dev.mjs脚本文件:

#!/usr/bin/env zx

await $`yarn build`; // prebuild if dist is empty
await Promise.all([$`yarn start:dev`, $`yarn build:dev`]); // run in parallel

现在,每当您想启动开发服务器时,只需运行yarn dev或npm run dev。

它将首先编译ts->js,然后在监视模式下并行运行typescrpt编译器和服务器。当您更改ts文件时->它将由tsc重新编译->nodemon将重新启动服务器。


高级编程使用

加载env变量,在监视模式下编译ts,然后从dist-on-changes(dev.mjs)重新运行服务器:

#!/usr/bin/env zx
import nodemon from "nodemon";
import dotenv from "dotenv";
import path from "path";
import { fileURLToPath } from "url";

// load env variables
loadEnvVariables("../env/.env");

await Promise.all([
  // compile in watch mode (will recompile on changes in .ts files)
  $`tsc -w`,
  // wait for tsc to compile for first time and rerun server on any changes (tsc emited .js files)
  sleep(4000).then(() =>
    nodemon({
      script: "dist/index.js",
    })
  ),
]);

function sleep(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

function getDirname() {
  return path.dirname(fileURLToPath(import.meta.url));
}

function loadEnvVariables(relativePath) {
  const { error, parsed } = dotenv.config({
    path: path.join(getDirname(), relativePath),
  });

  if (error) {
    throw error;
  }

  return parsed;
}

我已经从上面检查了几乎所有的解决方案,只有通过npm运行,我才能解决所有问题。与所有其他解决方案相比,主要优势是能够使用参数运行脚本。

{
  "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运行all的快捷方式--并行

这允许我使用npm-run-test:watch等参数运行命令。

编辑:

对于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 -- {*}\" --",