Typescript: Как разрешить абсолютные пути модулей для node.js?
Мне нужно, чтобы модули были решены на основе baseUrl
поэтому выходной код можно использовать для node.js
это мое src/server/index.ts
import express = require('express');
import {port, databaseUri} from 'server/config';
...
а это мой src/server/config/index.ts
export const databaseUri: string = process.env.DATABASE_URI || process.env.MONGODB_URI;
export const port: number = process.env.PORT || 1337;
Бег tsc
Я могу скомпилировать все файлы без ошибок, но вывод: dist/server/index.js
является
"use strict";
var express = require("express");
var config_1 = require("server/config");
...
В результате с Cannot find module 'server/config'
если я пытаюсь использовать его с node dist/sever/index.js
,
Зачем server/config
путь не разрешен никоим образом, поэтому можно использовать скомпилированный код или как его разрешить. Или что я делаю или неправильно думаю?
мой tsc --version
является 2.1.4
Это мое tsconfig.json
:
{
"compileOnSave": true,
"compilerOptions": {
"baseUrl": "./src",
"rootDir": "./src",
"module": "commonjs",
"target": "es5",
"typeRoots": ["./src/types", ".node_modules/@types"],
"outDir": "./dist"
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
Обратите внимание, я не хочу использовать ../../../../relative
пути.
4 ответа
Этот пост на машинописном github от Microsoft объясняет процесс разрешения модулей. В комментариях они объясняют, что то, что вы пытаетесь сделать, не может быть сделано.
эта функция, наряду с остальными возможностями разрешения модуля, предназначена только для того, чтобы помочь компилятору найти источник модуля по имени модуля. без изменений в выходной код JS. если вам требуется "папка2/ файл1", она всегда будет отправлена таким образом. Вы можете получить ошибки, если компилятор не может найти folder2/ file1.ts, но без изменений в выводе. https://github.com/Microsoft/TypeScript/issues/5039
а также
Компилятор не переписывает имена модулей. Имена модулей считаются идентификаторами ресурсов и отображаются в выходные данные в том виде, в каком они отображаются в источнике https://github.com/Microsoft/TypeScript/issues/5039.
Таким образом, испускаемый JS из машинописного текста НЕ переписывает путь к модулю для обнаруженных модулей, которые вы даете require
, Если вы запустите свое приложение в node
после компиляции (которая выглядит так, как будто вы используете экспресс), она будет использовать систему узловых модулей для разрешения ссылок на модули после компиляции машинописи. Это означает, что он будет уважать только относительные пути в вашем модуле, а затем обратится к node_modules для поиска зависимостей.
Вот как это должно работать. компилятору нужны пути, чтобы найти объявление вашего модуля. Имена модулей являются идентификаторами ресурсов и должны передаваться как есть и не изменяться. https://github.com/Microsoft/TypeScript/issues/5039
Вы в основном подтвердили это для себя в отчете в своем вопросе.
Один из способов сделать это — опубликовать ваш «модуль» в формате .
В Unixen (Linux, MacOS, Solaris и т. д.) вы можете просто сделать символическую ссылку на свой
server
папку в:
ln -s /path/to/your/project/dist/server /path/to/your/project/node_modules
Это в основном делает ваш код библиотекой. Node будет использовать обычное разрешение node_modules при запросе и импорте файлов.
Я не знаю, как это сделать в Windows, потому что я не использую Windows.
В качестве альтернативы вы можете просто скопировать сгенерированный код в
node_modules
после компиляции с машинописным текстом. Это будет работать с любой ОС:
# Unix shell example:
cp -r dist/server node_modules
С TypeScript это невозможно напрямую.
Однако, если вы установите(с двойной т, это не опечатка) и@zerollup/ts-transform-paths
, Вы можете.
ttypescript
вызывается
ttsc
вместо
tsc
.
Затем добавьте плагин ts-transform-paths в свой tsconfig, добавив его в параметры компилятора:
"plugins": [
{
"transform": "@zerollup/ts-transform-paths",
"exclude": ["*"]
}
]
Ваш окончательный tsconfig будет выглядеть так:
{
"compileOnSave": true,
"compilerOptions": {
"baseUrl": "./src",
"rootDir": "./src",
"module": "commonjs",
"target": "es5",
"typeRoots": ["./src/types", ".node_modules/@types"],
"outDir": "./dist",
"plugins": [
{
"transform": "@zerollup/ts-transform-paths",
"exclude": ["*"]
}
]
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
Изменить: это не работает для TypeScript 4.5+.
Обходной путь можно найти здесь .
Я также исследовал эту тему и, похоже, что на сегодняшний день нет готового решения:(
Хотя мне удалось добиться более или менее желаемого результата с помощью пакета npm для модуля-псевдонима - подробности см. В этом блоге.