简体   繁体   English

即使 tsc 成功解决了它,也找不到 Typescript 模块

[英]Cannot find Typescript module even though tsc successfully manages to resolve it

I have a Node.js project written in Typescript which is expected to run as a CLI, and am having trouble to import a module located out of the node_modules directory using an absolute path (relative paths work fine).我有一个用 Typescript 编写的 Node.js 项目,该项目预计将作为 CLI 运行,并且无法使用绝对路径(相对路径工作正常)导入位于node_modules目录之外的模块。 It might be important to mention that I am using the oclif framework for building my CLI.值得一提的是,我正在使用oclif 框架来构建我的 CLI。

My project is organized as follows:我的项目组织如下:

cli
 |--node_modules
 |--src
     |--my-module.ts
     |--subdir
          |--index.ts

Within my-module.ts I have:my-module.ts我有:

 export class MyClass {
     myClassFcn(s: string) {
         return 'result'
     }
 }

The index.ts script contains something like: index.ts脚本包含如下内容:

 import {MyClass} = require('my-module')

When I try to execute my app with ts-node, I get当我尝试使用 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

What I can't understand is that when I run tsc --traceResolution the module is correctly resolved:我无法理解的是,当我运行tsc --traceResolution ,模块被正确解析:

======== Module name 'my-module' was successfully resolved to '/home/eschmidt/Workspace/cli/src/my-module.ts'. ========

My tsconfig.json file contains:我的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/**/*"
  ]
}

I would greatly appreciate it if anyone could shed some light on this issue, or at least suggest where to look for further help.如果有人能对这个问题有所了解,或者至少建议去哪里寻求进一步的帮助,我将不胜感激。 In case more details are needed, please let me know.如果需要更多详细信息,请告诉我。

Thanks in advance!提前致谢!

It turns out that the problem was due to the fact that although both tsc and ts-node use baseUrl for absolute path resolution, neither of them perform any type of actual mapping from absolute to relative paths in the generated Javascript code.事实证明,问题是由于这样一个事实,尽管 tsc 和 ts-node 都使用baseUrl进行绝对路径解析,但它们都没有在生成的 Javascript 代码中执行从绝对路径到相对路径的任何类型的实际映射。 In other words, both the transpiled JS files and the code produced internally by ts-node end up having:换句话说,转译的 JS 文件和 ts-node 内部生成的代码最终都具有:

import  {MyClass} = require('my-module')

whereas I was expecting them to contain something like:而我期望它们包含以下内容:

import  {MyClass} = require('../my-module')

which prevented node's module loader from finding the module.这阻止了节点的模块加载器找到模块。 ts-node also did not work, I believe, because there was simply no tsconfig.json file to indicate the path mappings.我相信 ts-node 也不起作用,因为根本没有 tsconfig.json 文件来指示路径映射。

Although confusing IMO, and not properly documented, this is expected behavior, though, as discussed here .尽管 IMO 令人困惑,并且没有正确记录,但这是预期的行为,正如此处所讨论的。 As of now, absolute to relative path mapping is not supported by Typescript (see https://github.com/Microsoft/TypeScript/issues/15479 ).截至目前,Typescript 不支持绝对到相对路径的映射(请参阅https://github.com/Microsoft/TypeScript/issues/15479 )。

In order to avoid the situation known as path hell, which means having very deep relative import paths, I found module-alias and tsmodule-alias to be very useful.为了避免被称为路径地狱的情况,这意味着具有非常深的相对导入路径,我发现module-aliastsmodule-alias非常有用。 These modules alter the behavior of the module loader so that it automatically maps aliases to relative paths.这些模块改变了模块加载器的行为,以便它自动将别名映射到相对路径。

For more information about the problem, refer to this issue on Github.有关该问题的更多信息,请参阅 Github 上的此问题

Another solution that may be relevant is to run node with NODE_PATH=dist node dist/index.js .另一个可能相关的解决方案是使用NODE_PATH=dist node dist/index.js运行节点。 This essentially specifies to node what path each absolute import (relative to baseUrl ) should use这实质上指定node每个绝对导入(相对于baseUrl )应使用的路径

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM