我创建了一个仅 ESM 的包,它公开所有文件,而不是在
exports
中定义
package.json
{
"name": "@org/runtime",
"version": "0.0.0-development",
"description": "Runtime library",
"module": "index.js",
"type": "module",
"scripts": {
"b": "pnpm build",
"prebuild": "rm -rf dist",
"build": "tsc --project tsconfig.build.json && pnpm build:copy-dts && tsc-alias && cp package.json dist/",
"build:copy-dts": "copyfiles -V -u 1 src/**/*.d.ts src/*.d.ts dist",
"lint": "eslint .",
"test": "vitest",
"test:ci": "vitest --coverage",
"release": "semantic-release"
},
"devDependencies": {
"tsc-alias": "^1.8.10",
"typescript": "^5.5.3",
},
"dependencies": {
},
"engines": {
"node": ">=22"
}
}
我得到这样的文件结构:
├── background-job
│ ├── index.d.ts
│ └── index.js
├── logger
│ ├── formatter
│ │ ├── console-formatter.d.ts
│ │ ├── console-formatter.js
│ │ ├── formatter.d.ts
│ │ ├── formatter.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── json-formatter.d.ts
│ │ └── json-formatter.js
│ ├── index.d.ts
│ ├── index.js
│ ├── shared.d.ts
│ └── shared.js
├── package.json
├── request-context
│ ├── fastify.d.ts
│ ├── fastify.js
│ ├── index.d.ts
│ ├── index.js
│ ├── plugin.d.ts
│ └── plugin.js
├── result.d.ts
├── result.js
├── tests
│ ├── setup.d.ts
│ └── setup.js
├── types.d.ts
├── validations
│ ├── is-truthy.d.ts
│ └── is-truthy.js
└── validator
├── index.d.ts
├── index.js
├── schema-extensions.d.ts
├── schema-extensions.js
└── yup.d.ts
在我的主项目中,我有这个 tsconfig.json:
{
"compilerOptions": {
"target": "ES2023",
"module": "NodeNext",
"esModuleInterop": true,
"moduleResolution": "NodeNext",
"lib": [
"ESNext"
],
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"outDir": "dist",
"rootDir": "src",
"baseUrl": ".",
"typeRoots": [
"node_modules/@types"
],
"types": [
"node"
],
"declaration": false,
"sourceMap": false,
"paths": {
"@/*": [
"src/*"
]
}
},
"include": [
"src/**/*.ts",
"node_modules/@types/node/globals.d.ts",
"node_modules/vitest/globals.d.ts",
"node_modules/.pnpm/[email protected]_@[email protected]/node_modules/vitest/globals.d.ts"
],
"exclude": [
"node_modules",
"dist"
],
"tsc-alias": {
"resolveFullPaths": true,
"verbose": true
}
}
安装我的包后,我尝试像这样导入它:
import { Logger } from '@org/runtime/logger';
ESlint,我的 IDE 和 tsc 可以在该导入语句上运行,没有任何警告/错误。我可以毫无问题地进行 lint 和构建。然后,当我运行转译的代码时,出现错误
Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/my-project/node_modules/@org/runtime/logger' is not supported resolving ES modules imported from /my-project/index.js
Did you mean to import "@org/runtime/logger/index.js"?
如果我将
index.js
添加到我的导入语句中,我就可以毫无问题地运行该项目。如何让 TSC 在构建期间发现这些问题?或者我怎样才能让IDE意识到这个问题?
我宁愿避免依赖 eslint,这样我就可以在构建项目时捕捉到这一点。
首先 - 在导出部分下的 package.json 中定义完整路径:
"exports": {
"./logger": "path/to/logger/index.js"
}
然后它会更漂亮一点,而且这样 ts 和 ide 就可以捕获它,因为你使用显式定义的路径。
第二 - 我不认为 ts 在不使用上面提到的情况下做到这一点,它有更多的样式和类型,它假设当你导入时你做对了。
虽然你说你不想这样做,但我知道的选择是使用
eslint-plugin-import
,它正是这样做的。
第三 - 您可以在构建中添加 eslint 检查(实际上是推荐的),然后在构建过程中捕获它。
最后,你的IDE中可能有一个扩展,只需搜索它即可。