Не удается найти модуль Typescript, хотя tsc успешно может его решить
У меня есть проект Node.js, написанный на Typescript, который, как ожидается, будет работать как CLI, и у меня возникли проблемы с импортом модуля, расположенного вне node_modules
каталог, использующий абсолютный путь (относительные пути работают нормально). Возможно, важно упомянуть, что я использую инфраструктуру oclif для создания своего 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/**/*"
]
}
Я был бы очень признателен, если бы кто-нибудь смог пролить свет на эту проблему или хотя бы предложить, где искать дополнительную помощь. В случае необходимости более подробной информации, пожалуйста, дайте мне знать.
Заранее спасибо!
1 ответ
Оказывается, проблема была в том, что хотя и tsc, и ts-node используют baseUrl
для абсолютного разрешения пути ни один из них не выполняет никакого фактического отображения от абсолютных до относительных путей в сгенерированном коде Javascript. Другими словами, и транспортируемые JS-файлы, и код, созданный внутренне с помощью ts-узла, в конечном итоге имеют:
import {MyClass} = require('my-module')
тогда как я ожидал, что они будут содержать что-то вроде:
import {MyClass} = require('../my-module')
что помешало загрузчику модуля узла найти модуль. Я полагаю, что ts-node также не работал, потому что просто не было файла tsconfig.json, чтобы указать пути.
Хотя это вводит в заблуждение ИМО и не документировано надлежащим образом, это ожидаемое поведение, как описано здесь На данный момент сопоставление абсолютного и относительного путей не поддерживается Typescript (см. https://github.com/Microsoft/TypeScript/issues/15479).
Чтобы избежать ситуации, известной как путь к аду, что означает наличие очень глубоких относительных путей импорта, я обнаружил, что module-alias и tsmodule-alias очень полезны. Эти модули изменяют поведение загрузчика модулей, так что он автоматически сопоставляет псевдонимы с относительными путями.
Для получения дополнительной информации о проблеме обратитесь к этой проблеме на Github.
Другое решение, которое может быть актуальным, - запустить узел с NODE_PATH=dist node dist/index.js
. Это по существу указывает наnode
какой путь каждый абсолютный импорт (относительно baseUrl
) следует использовать