不幸的是,npm 没有也不打算提供允许将参数传递到 npm 脚本中间的内置功能(如 here 所述)。参数只能传递到脚本的末尾。
对于 Linux 和 macOS,您可以根据我的回答 here 在 npm-scripts 中使用 bash functions 将参数传递到脚本中间。然而,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]});
说明:
在第一行我们require 内置节点execSync()。我们将利用它来运行cross-env 并设置环境变量。
-
Nodes builtin process.argv 获取通过命令行传递的参数。节点process.argv 中的前两项是:
- 运行 JavaScript 文件的可执行文件的路径。
- 正在执行的 JavaScript 文件的路径。
-
但是,我们只对数组中第三项以后的元素感兴趣 - 因为这些将是您通过 CLI 传递的参数。这些行是什么;
const args = process.argv.splice(2, process.argv.length - 2)
.map(arg => arg.replace(/^--/, ''));
创建一个args 变量并分配一个数组,其中包含通过 CLI 传递的每个参数。使用 splice() 方法从数组中省略了第 2 点中的前两项。在map() 方法中,我们从每个参数中删除-- 前缀。
-
最后一行阅读:
execSync(`cross-env ${args.join(' ')} my-app`, {stdio:[0, 1, 2]});
调用cross-env 并使用Template Literals 和数组join() 方法将参数作为字符串放置。 stdio 部分在子进程中为stdin、stdout、stderr 配置管道。
注意:如果您的目标是不支持 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 脚本。
可以通过 CLI 调用 npm start 脚本,方法是运行:
$ npm start -- --env=dev --host=localhost --port=1234
在调用 npm 的 start 脚本时,不需要 run 部分,即 npm run start ...。