node.js - Typescript 路径别名在运行时未正确解析
我正在运行 VS Code,目前正在尝试在我的 TypeScript 项目中设置一些别名。
我的开发环境依赖于 nodemon 和 ts-node,代码会被编译到 dist 文件夹。
到目前为止,我成功让 Typescript Hero 使用别名来管理导入:
到目前为止,我的文件夹结构是:
.
└─┬ src
├──modules
├────Category
├────Ressource
├──shared
├────debug
// tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"pretty": true,
"sourceMap": true,
"target": "es6",
"outDir": "./dist",
"baseUrl": "./src",
"paths": {
"@shared/*": [
"shared/*"
],
"@modules/*": [
"modules/*"
]
},
"resolveJsonModule": true,
"esModuleInterop": true
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules",
"**/*.spec.ts",
"**/*.test.ts",
]
}
这是第一个失败的别名导入。
//Server.ts file
import Print from '@shared/debug/Print.class';
import App from './App';
const MyApp: App = new App();
MyApp.ExpressApp.listen(MyApp.Config.ExpressPort, () => {
Print.Log('Express server listening on port ' + MyApp.Config.ExpressPort);
});
但是,我收到一个错误:“无法找到模块 '@shared/debug/Print.class'” 在 “cross-env NODE_ENV=development nodemon ts-node ./src/server.ts”。
这就是我的立场。
现在,我已经阅读了一些在 SO 上的问答,似乎即使我设法在开发环境中让别名工作,在生产环境中也会失败,因为我是在 TypeScript 的 src 文件夹中运行,而我的交付物是构建在 dist 中的?如果是这样,有什么方法可以补救吗?非常感谢
答案#1
问题出现在运行时对节点路径别名的解析上。即使 TypeScript 在运行时由 ts-node 执行,节点也无法按原样解析这些别名。(我认为)
但这只是冰山一角。我后来在我的 Jest 设置中,以及在 JS 运行时都会遇到它。
我必须找到一种方法,在我拥有的每个运行时中解释我的别名。有一些 npm 包,但很多都需要更多的声明。
而且我不想在每个配置文件中都声明我的别名,只想依赖我的 tsconfig 文件。
经过多次测试,只有两个节点模块需要安装:tsconfig-paths 用于 ts-node 上的 TypeScript 运行时执行,以及 @ef-carbon/tspm 用于将我的别名转换到构建目标。
npm i -D tsconfig-paths @ef-carbon/tspm
对于 ts-node,该脚本被修改为:
ts-node -r tsconfig-paths/register ./src/server.ts
对于你的 js 编译,只需要运行:
ef-tspm
对于 jest,需要 ts-jest,我已经有了,但它没有正确配置。我使用内置的助手来设置我的路径。我的 jest 配置文件现在看起来是这样的:
//jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig');
module.exports = {
roots: ['<rootDir>/src'],
globals: {
'ts-jest': {
tsConfig: 'tsconfig.json',
diagnostics: {
warnOnly: true,
},
},
},
clearMocks: true,
coverageDirectory: 'coverage',
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
moduleFileExtensions: ['js', 'json', 'jsx', 'node', 'ts', 'tsx'],
testEnvironment: 'node',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/src/' }),
pathToJest: 'npm test',
preset: 'ts-jest',
testMatch: null,
};
这是我在 package.json 中的脚本长这个样子
"scripts": {
"dev:ts": "cross-env NODE_ENV=development nodemon",
"dev:js": "cross-env NODE_ENV=development npm run start:js",
"staging": "cross-env NODE_ENV=staging npm run start:js",
"production": "cross-env NODE_ENV=production npm run start:js",
"test": "cross-env NODE_ENV=testing jest --runInBand",
"test:debug": "npm run test --detectOpenHandles",
"start:js": "npm run build && nodemon --config nodemon-js.json",
"build": "npm run compile && npm run post:compile && npm run copyAssets",
"compile": "tsc",
"post:compile": "ef-tspm",
"copyAssets": "copyfiles -e ./src/**/*.ts -e ./src/**/*sample* -e ./src/**/*.json -u 1 ./src/**/* ./dist/"
},
看看情况如何,我可能会之后再添加一个 grunt/gulp 的解决方案。但目前,这已经足够好了。
答案#2
我遇到了同样的问题,CrazyYoshi 的解决方案在我的情况下并没有正常工作。
我通过在 tsconfig.json 中放入这段代码解决了这个问题:
{
"ts-node": {
// Do not forget to `npm i -D tsconfig-paths`
"require": ["tsconfig-paths/register"]
}
}
之后不要忘记安装 tsconfig-paths 模块:
npm i -D tsconfig-paths
文档: https://typestrong.org/ts-node/docs/paths/
答案#3
你正在使用 ts-node 和 nodemon 来运行你的代码,所以你应该将此添加到你的 tsconfig.json 文件中:
{
"ts-node": {
"require": ["tsconfig-paths/register"]
}
}
然后将 tsconfig-paths/register 安装为开发依赖。
npm install --save-dev tsconfig-paths
更新: 如果你正在寻找一种 无需配置 的解决方案,可以考虑在你的项目中使用 tsx 作为 ts-node 和 nodemon 的替代方案。
你可以这样做:
- 将
ts-node替换为tsx。 - 使用
tsx --watch而不是nodemon。
参考文献
- 路径和基本网址
- 路径映射
答案#4
2023年3月
刚刚花了好几个小时才勉强让它工作。最后,我干脆完全放弃了 ts-node,安装了 tsx,它开箱即用,直接就能工作。
显然,这最终会加入到 ts-node 中,尽管这个 PR 看起来已经死了,所以谁知道呢:
https://github.com/TypeStrong/ts-node/pull/1585
同时,如果你真的想坚持使用 ts-node,你可能会发现以下内容有用:
https://www.npmjs.com/package/@bleed-believer/path-alias
https://github.com/TypeStrong/ts-node/issues/1007
https://github.com/TypeStrong/ts-node/discussions/1450#discussioncomment-1806115

