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 для модуля-псевдонима - подробности см. В этом блоге.

Другие вопросы по тегам