简体   繁体   English

Typescript:如何解析 node.js 的绝对模块路径?

[英]Typescript: How to resolve absolute modules paths for node.js?

I need modules to be resolved basing on baseUrl so output code is usable for node.js我需要基于baseUrl解析模块,所以 output 代码可用于 node.js

this is my src/server/index.ts这是我的src/server/index.ts

import express = require('express');
import {port, databaseUri} from 'server/config';

...

and this is my src/server/config/index.ts这是我的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;

Running tsc I'm able to compile all files without erros, but output: dist/server/index.js is运行tsc我能够编译所有文件而没有错误,但是 output: dist/server/index.js

"use strict";
var express = require("express");
var config_1 = require("server/config");

...

Resulting with Cannot find module 'server/config' if I'm trying to use it with node dist/sever/index.js .如果我尝试将它与node dist/sever/index.js一起使用,则会导致Cannot find module 'server/config'

Why server/config path is not resolved in any way so it would be possible to use compiled code or how to make it resolve it.为什么server/config路径没有以任何方式解析,所以可以使用编译代码或如何让它解析它。 Or what am I doing or thinking wrong way?或者我在做什么或以错误的方式思考?

My tsc --version is 2.1.4我的tsc --version2.1.4

This is my tsconfig.json :这是我的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"
  ]
}

Note I don't want to use ../../../../relative paths.注意我不想使用../../../../relative路径。

This post on Microsoft's typescript github explains their module resolution process. 微软打字稿github上的这篇文章解释了其模块解析过程。 In the comments they explain that what you're trying to do can't be done. 他们在评论中解释说,您要做的事情无法完成。

this feature, along with the rest of the module resolution capabilities, are only to help the compiler find the module source given a module name. 此功能以及其余的模块解析功能仅用于帮助编译器在给定模块名称的情况下找到模块源。 no changes to the output js code. 无需更改输出js代码。 if you require "folder2/file1" it will always be emitted this way. 如果您需要“ folder2 / file1”,它将始终以这种方式发出。 you might get errors if the compiler could not find a folder2/file1.ts, but no change to the output. 如果编译器找不到folder2 / file1.ts,但对输出没有任何更改,则可能会出错。 https://github.com/Microsoft/TypeScript/issues/5039#issuecomment-206451221 https://github.com/Microsoft/TypeScript/issues/5039#issuecomment-206451221

and

The compiler does not rewrite module names. 编译器不会重写模块名称。 module names are considered resource identifiers, and are mapped to the output as they appear in the source https://github.com/Microsoft/TypeScript/issues/5039#issuecomment-232470330 模块名称被视为资源标识符,并按照它们在源https://github.com/Microsoft/TypeScript/issues/5039#issuecomment-232470330中显示的方式映射到输出

So, the emitted JS from typescript does NOT rewrite the module path for the discovered modules you give to require . 因此,从typescript发出的JS不会为您提供给require的发现模块重写模块路径。 If you run your app in node after compilation (which it looks like you are with express), then it will use the node module system to resolve the module references after typescript compilation. 如果您在编译后在node运行应用程序(看起来像使用express一样),那么它将在打字稿编译后使用节点模块系统来解析模块引用。 This means that it will only respect relative paths in your module and then it will fall back to node_modules to find dependencies. 这意味着它将仅遵循模块中的相对路径,然后将退回到node_modules来查找依赖项。

that is how it is meant to work. 这就是它的工作方式。 the compiler needs the paths to find the declaration of your module. 编译器需要找到模块声明的路径。 module names are resource identifiers and should be emitted as is and not altered. 模块名称是资源标识符,应按原样发出,并且不得更改。 https://github.com/Microsoft/TypeScript/issues/5039#issuecomment-255870508 https://github.com/Microsoft/TypeScript/issues/5039#issuecomment-255870508

You have basically confirmed this for yourself in the emitted output in your question. 您基本上已经在问题的输出中为自己确认了这一点。

One way to do this is to publish your server "module" in node_modules .一种方法是在node_modules中发布您的server “模块”。

On Unixen (Linux, MacOS, Solaris etc.) you can simply symlink your server folder to node_modules :在 Unixen(Linux、MacOS、Solaris 等)上,您可以简单地将您的server文件夹符号链接到node_modules

ln -s /path/to/your/project/dist/server /path/to/your/project/node_modules

This basically makes your code a library.这基本上使您的代码成为一个库。 Node will use the usual node_modules resolution when requiring and importing files. Node 在需要和导入文件时将使用通常的 node_modules 解析。

I'm not sure how to do this on Windows because I don't use Windows.我不确定如何在 Windows 上执行此操作,因为我不使用 Windows。

Alternatively you can just copy the generated code to node_modules after compiling with typescript. This would work with any OS:或者,您可以在使用 typescript 编译后将生成的代码复制到node_modules 。这适用于任何操作系统:

# Unix shell example:
cp -r dist/server node_modules

With TypeScript, this is not possible directly.对于 TypeScript,这是不可能直接实现的。

However, if you install ttypescript (with a double t, that's not a typo) and @zerollup/ts-transform-paths , you can.但是,如果您安装ttypescript (带有双 t,这不是拼写错误)和@zerollup/ts-transform-paths ,则可以。

ttypescript is invoked by ttsc instead of tsc . ttypescriptttsc而不是tsc调用。

Then, add the ts-transform-paths plugin to your tsconfig by adding it to the compiler options:然后,通过将 ts-transform-paths 插件添加到编译器选项,将其添加到您的 tsconfig 中:

"plugins": [
      {
        "transform": "@zerollup/ts-transform-paths",
        "exclude": ["*"]
      }
    ]

Your final tsconfig would look like this:您最终的 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"
  ]
}

Edit: This does not work for TypeScript 4.5+.编辑:这不适用于 TypeScript 4.5+。

A workaround can be found here .可以在此处找到解决方法。

I've researched the topic as well and seems that as of today there is still no out of the box solution :( 我也研究了该主题,并且似乎到目前为止,还没有开箱即用的解决方案:(

Though I've managed to achieve more or less the desired result using module-alias npm package - see this blog post for details. 尽管我已经设法使用module-alias npm软件包或多或少地获得了预期的结果-详情请参阅此博客文章

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

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