我们的团队构建了一个用于维护的小型 CLI。 package.json 使用
bin
属性指定路径,一切都很好; "bin": { "eddy": "./dist/src/cli/entry.js"}
自动补全是通过使用
[email protected]
实现的。 但是我们最近将项目转换为使用 es6 模块,因为迁移到了 Sveltekit,即 package.json 现在包含 type: module
。因此,CLI 现在仅在我们运行时才有效:
什么有效
node --experimental-specifier-resolution=node ./dist/src/cli/entry.js help
但是,如果我们在没有标志的情况下运行它,我们会收到错误“找不到模块”:
Error [ERR_MODULE_NOT_FOUND]: Cannot find module...
所以问题是
我们能否以某种方式“始终”将
experimental-specifier-resolution=node
添加到 CLI - 这样我们就可以继续使用简写 eddy
,并利用自动完成功能?
这里有两种可能的解决方案。
您的
entry.js
文件应以 #!/usr/bin/env node
等 shebang 开头。您不能直接在此处指定标志,但是,如果您可以直接在 shebang 中提供节点的绝对路径,则可以指定标志。
假设您在
/usr/bin/node
中安装了节点,您可以在entry.js
中编写shebang,如下所示:
#!/usr/bin/node --experimental-specifier-resolution=node
(使用
which node
查找绝对路径)
但是,这不是一个非常便携的解决方案。您不能总是假设每个人都将节点安装在同一路径中。还有一些可能使用 nvm 来管理版本,并且可以在不同的路径中有多个版本。这就是为什么我们首先使用
/usr/bin/env
来查找所需的节点安装的原因。这就引出了第二种解决方案。
您可以创建一个 shell 脚本,该脚本将使用所需的标志调用 cli 入口点。该 shell 脚本可以在
package.json
bin
部分指定。
shell 脚本 (
entry.sh
) 应如下所示:
#!/usr/bin/env bash
/usr/bin/env node --experimental-specifier-resolution=node ./entry.js "$@"
然后,在您的
package.json
中,将 bin 替换为:
"bin": { "eddy": "./dist/src/cli/entry.sh"}
因此,当您运行
eddy
时,它将使用带有所需标志的 entry.js
来运行 node
。命令中的 "$@"
将替换为您传递给 eddy
的任何参数。
所以
eddy help
将翻译为 /usr/bin/env node --experimental-specifier-resolution=node ./entry.js help
作为 Vivek 答案的补充,使 bin 可以从任何地方执行是可以预期的
#!/usr/bin/env bash
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
node --experimental-specifier-resolution=node "$SCRIPT_DIR/entry.js" "$@"
只需将脚本添加到您的package.json中:
假设index.js是您的入口点并且package.json位于同一目录中
{
"scripts": {
"start": "node --experimental-specifier-resolution=node index.js"
}
}
然后你就可以在控制台上运行了:
npm start