如何使用实验说明符分辨率=节点运行node.js cli?

Dau*_*eDK 14 node.js yargs

我们的团队构建了一个用于维护的小型 CLI。package.json 指定了属性的路径bin,一切都很好;"bin": { "eddy": "./dist/src/cli/entry.js"}

自动完成是通过使用 来实现的yargs@17.0.1然而,由于迁移到 Sveltekit,我们最近将项目转换为使用 es6 模块,即 package.json 现在包含type: module. 因此,CLI 现在仅在我们运行以下命令时才有效:

什么有效

node --experimental-specifier-resolution=node ./dist/src/cli/entry.js help
Run Code Online (Sandbox Code Playgroud)

但是,如果我们在没有该标志的情况下运行此命令,则会收到错误“找不到模块”:

Error [ERR_MODULE_NOT_FOUND]: Cannot find module...
Run Code Online (Sandbox Code Playgroud)

所以问题是

我们是否可以以某种方式“始终”将 the 添加experimental-specifier-resolution=node到 CLI - 这样我们就可以继续使用简写eddy并利用自动完成功能?

Viv*_*vek 12

这里有两种可能的解决方案。

解决方案1

您的entry.js文件应该以 shebang 开头,例如#!/usr/bin/env node. 您不能在此处直接指定该标志,但是,如果您可以直接在 shebang 中提供节点的绝对路径,则可以指定该标志。

假设你已经在 中安装了节点/usr/bin/node,你可以像这样编写 shebang entry.js

#!/usr/bin/node --experimental-specifier-resolution=node
Run Code Online (Sandbox Code Playgroud)

(用于which node查找绝对路径)

然而,这不是一个非常便携的解决方案。您不能总是假设每个人都将节点安装在同一路径中。另外,有些可能使用 nvm 来管理版本,并且可以在不同路径中拥有多个版本。/usr/bin/env这就是我们首先用来查找所需节点安装的原因。这导致了第二种解决方案。

解决方案2

您可以创建一个 shell 脚本,该脚本将使用所需的标志调用 cli 入口点。该 shell 脚本可以在 部分中指定package.json bin

shell 脚本 ( entry.sh) 应如下所示:

#!/usr/bin/env bash
/usr/bin/env node --experimental-specifier-resolution=node ./entry.js "$@"
Run Code Online (Sandbox Code Playgroud)

然后,在您的 中package.json,将 bin 替换为:

"bin": { "eddy": "./dist/src/cli/entry.sh"}
Run Code Online (Sandbox Code Playgroud)

因此,当您运行时eddy,它将运行带有 required 标志的entry.jsusing 。node命令中的"$@"将会替换为您传递给 的任何参数eddy

所以eddy help将翻译为/usr/bin/env node --experimental-specifier-resolution=node ./entry.js help

  • 如果您尝试建立一个打字稿项目,这将是一场噩梦。感谢您的帮助 (2认同)
  • @Vivek 你确定不能将标志作为 hashbang 的一部分传递吗?这似乎对我有用。我已成功使用它来执行具有 ESM 和 TS 支持的 Node [此处](https://github.com/0x80/firestore-facade/blob/main/packages/cli/src/cli.ts)。我只在 MacOS 上测试过这个...解决方案 2 我无法工作,因为 ./entry.js 是从 CWD 解析的,而不是 bash 脚本的文件位置。就我而言,这是有问题的,因为像 OP 一样,我将其作为 NPM 包 bin 脚本执行。CWD 将成为执行命令的项目根目录。 (2认同)