将环境变量作为参数传递给 npm 脚本的跨平台方式

Cross-platform way to pass environment variables as arguments to npm scripts

从 Windows 或 Linux,我想要一种将 args 传递给 npm script 的方法,但要将它们作为环境变量注入

在命令行中,我将以这种方式开始我的项目:

npm run start -- --env=dev --host=localhost --port=1234

为了使用我的 cli 参数并将它们作为 env 变量注入而不考虑平台,我使用了 cross-env npm 包:

package.json

  "scripts": {
    "start": "cross-env env=%env% host=%host% port=%port% my-app"
  },

我知道上面的语法无效,但是 start 脚本能以某种方式使用我传递的参数而不是将它们转发给 my-app 吗?

不幸的是,npm 没有,也不打算提供允许将参数传递到 npm 脚本中间的内置功能(如所述here .参数只能传递到脚本的末尾。

对于 Linux 和 macOS,您可以使用 bash functions in npm-scripts to pass arguments to the middle of a script, as per my answer 。然而 Windows 会被这样的解决方案噎住。

由于需要跨平台兼容性,请考虑将当前在 start 脚本中的逻辑移动到单独的 nodejs 实用程序脚本中。然后可以通过名为 start.

的 npm 脚本调用 nodejs 脚本

下面介绍如何以跨平台兼容的方式实现你的需求


1。自定义 nodejs 实用程序脚本。

创建一个nodejs脚本如下。让我们将脚本命名为 start.js 并将其保存在项目目录的根目录中,即与 package.json 文件当前所在。

const execSync = require('child_process').execSync;

const args = process.argv.splice(2, process.argv.length - 2)
    .map(arg => arg.replace(/^--/, ''));

execSync(`cross-env ${args.join(' ')} my-app`, {stdio:[0, 1, 2]});

解释:

  1. 在第一行我们 require 个节点内置 execSync()。我们将利用它 运行 cross-env 并设置环境变量。

  2. Nodes builtin process.argv 获取通过命令行传递的参数。节点 process.argv 中的前两项是:

    • 可执行文件 运行 到 JavaScript 文件的路径。
    • 正在执行的JavaScript文件的路径。
  3. 但是,我们只对数组中第三项以后的元素感兴趣 - 因为这些将是您通过 CLI 传递的参数。这些行读作;

    const args = process.argv.splice(2, process.argv.length - 2)
        .map(arg => arg.replace(/^--/, ''));
    

    创建一个 args 变量并分配一个数组,其中包含通过 CLI 传递的每个参数。使用 splice() method. In the map() 方法从数组中省略第 2 点中的前两项,我们从每个参数中删除 -- 前缀。

  4. 最后一行阅读:

    execSync(`cross-env ${args.join(' ')} my-app`, {stdio:[0, 1, 2]});
    

    调用 cross-env 并将参数作为字符串使用 Template Literals and the Array join() method. The stdio 部分在子进程中为 stdinstdoutstderr 配置管道.

注意: 如果您的目标节点的旧版本不支持 Template Literals 那么您可以将此行替换为以下内容反而。这使用 + 运算符处理字符串连接:

execSync('cross-env ' + args.join(' ') + ' my-app', {stdio:[0, 1, 2]});

同样,如果不支持 ES6 箭头函数,请更改 map() 以使用标准函数。例如:

.map(function(arg) {
  return arg.replace(/^--/, '');
});

2。 package.json 脚本。

package.json 中重新定义您的 start 脚本,如下所示:

"scripts": {
  "start": "node start"
},

这里我们要求节点调用start.js脚本。

注意 如果您希望将 start.js 文件保存在与上述根目录不同的目录位置您的项目目录,那么您需要根据需要定义 start.js 的路径。该路径应相对于 package.json。例如:

"scripts": {
  "start": "node ./the/path/to/start"
},

3。 运行 npm 脚本。

npm start 脚本可以通过 运行ning:

通过 CLI 调用
$ npm start -- --env=dev --host=localhost --port=1234

调用 npm 的 start 脚本时不需要 run 部分,即 npm run start ...