如何使用experimental-specifier-resolution=node运行node.js cli? tsconfig.jsonPackage.json

问题描述

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

自动完成是通过使用 yargs@17.0.1 实现的。 然而我们最近将项目转换为使用 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 并利用自动完成功能

解决方法

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

解决方案 1

您的 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 查找所需节点安装的原因。这就引出了第二种解决方案。

解决方案 2

您可以创建一个 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

,

确保您的 CLI 的 tsconfig.json 配置了这些编译器选项。您可以参考 to csv,这是我在 TypeScript 和 ES6 语法中编写的CLI

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",/* Specify ECMAScript target version: 'ES3' (default),'ES5','ES2015','ES2016','ES2017','ES2018','ES2019','ES2020',or 'ESNEXT'. */
    "module": "commonjs",/* Specify module code generation: 'none','commonjs','amd','system','umd','es2015','es2020',or 'ESNext'. */
    "resolveJsonModule": true,/* Allows for importing,extracting types from and generating .json files */
    "declaration": false,/* Generates corresponding '.d.ts' file. */
    "downlevelIteration": true,/* Provide full support for iterables in 'for-of',spread,and destructuring when targeting 'ES5' or 'ES3'. */
    "strict": true,/* Enable all strict type-checking options. */
    "esModuleInterop": true,/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    "skipLibCheck": true,/* Skip type checking of declaration files. */
  }
}

Package.json

您还可以参考此 package.json 中的 bin 属性,它允许通过在终端中运行 rapid-react 命令来运行 CLI。

{
  "name": "rapid-react","version": "...","description": "A light weight interactive CLI Automation Tool ?️ for rapid scaffolding of React apps with Create React App under the hood. ⚛️","main": "lib/index.js","scripts": {
    "start": "npx nodemon --no-stdin --watch 'src/**/*.ts' --exec npx ts-node src/index.ts","test": "...","lint": "...","build": "...","prebuild": "..."
  },"files": [
    "lib"
  ],"repository": {
    "type": "git","url": "https://github.com/vinaysharma14/rapid-react.git"
  },"author": "Vinay Sharma <vinaysharma7811@gmail.com> (https://www.linkedin.com/in/vinaysharma-/)","license": "MIT","bin": {
    "rapid-react": "lib/index.js"
  },"keywords": [
    "..."
  ],"bugs": {
    "url": "..."
  },"homepage": "...","dependencies": {
    "...": "...",},"devDependencies": {
    "...": "...","ts-node": "^9.0.0","typescript": "^4.1.2"
  }
}