我有一个用Typescript编写的Node.js项目,它应该作为CLI运行,并且无法使用绝对路径导入位于node_modules
目录之外的模块(相对路径工作正常) 。可能很重要的是,我正在使用oclif framework来构建我的CLI。
我的项目安排如下:
cli
|--node_modules
|--src
|--my-module.ts
|--subdir
|--index.ts
在my-module.ts
内我有:
export class MyClass {
myClassFcn(s: string) {
return 'result'
}
}
index.ts
脚本包含以下内容:
import {MyClass} = require('my-module')
当我尝试使用ts-node执行我的应用程序时,我得到了
(node:10423) [MODULE_NOT_FOUND] Error Plugin: cli: Cannot find module 'my-module'
module: @oclif/config@1.6.17
task: toCached
plugin: cli
root: /home/eschmidt/Workspace/cli
Error Plugin: cli: Cannot find module 'my-module'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:571:15)
at Function.Module._load (internal/modules/cjs/loader.js:497:25)
at Module.require (internal/modules/cjs/loader.js:626:17)
at require (internal/modules/cjs/helpers.js:20:18)
at Object.<anonymous> (/home/eschmidt/Workspace/cli/src/commands/create/index.ts:5:1)
at Module._compile (internal/modules/cjs/loader.js:678:30)
at Module.m._compile (/home/eschmidt/Workspace/cli/node_modules/ts-node/src/index.ts:403:23)
at Module._extensions..js (internal/modules/cjs/loader.js:689:10)
at Object.require.extensions.(anonymous function) [as .ts] (/home/eschmidt/Workspace/cli/node_modules/ts-node/src/index.ts:406:12)
at Module.load (internal/modules/cjs/loader.js:589:32)
module: @oclif/config@1.6.17
task: toCached
plugin: my-plugin
root: /home/eschmidt/Workspace/cli
我无法理解的是,当我运行tsc --traceResolution
时,模块已正确解析:
======== Module name 'my-module' was successfully resolved to '/home/eschmidt/Workspace/cli/src/my-module.ts'. ========
我的tsconfig.json
文件包含:
{
"compilerOptions": {
"declaration": true,
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
"importHelpers": true,
"module": "commonjs",
"sourceMap": true,
"outDir": "./lib",
"pretty": true,
"rootDirs": [
"./src/"
],
"strict": true,
"target": "es2017",
"baseUrl": "src"
},
"include": [
"./src/**/*"
]
}
如果有人能对这个问题有所了解,或者至少建议在哪里寻求进一步的帮助,我将不胜感激。如果需要更多详细信息,请告知我们。
提前致谢!
答案 0 :(得分:11)
事实证明,问题是由于虽然tsc和ts节点都使用baseUrl
进行绝对路径解析,但它们都没有执行从生成的绝对路径到相对路径的任何类型的实际映射Javascript代码。换句话说,转换后的JS文件和ts-node内部生成的代码最终都具有:
import {MyClass} = require('my-module')
虽然我期待它们包含类似的内容:
import {MyClass} = require('../my-module')
阻止节点的模块加载器找到模块。我相信ts-node也没用,因为根本没有tsconfig.json文件来指示路径映射。
虽然IMO令人困惑,但没有正确记录,但这是预期的行为,正如here所讨论的那样。截至目前,Typescript不支持绝对到相对路径映射(参见https://github.com/Microsoft/TypeScript/issues/15479)。
为了避免被称为路径地狱的情况,这意味着拥有非常深的相对导入路径,我发现module-alias和tsmodule-alias非常有用。这些模块改变了模块加载器的行为,因此它会自动将别名映射到相对路径。
有关该问题的更多信息,请参阅Github上的issue。
答案 1 :(得分:1)
另一个可能相关的解决方案是使用conf/users-credentials.properties
运行节点。这实际上是为NODE_PATH=dist node dist/index.js
指定每个绝对导入(相对于node
)应使用的路径