tsconfig.json 中的路径在 tsc 后无法使用

9

在我的 Express 项目中,我从路径中导入 @common/foo。得益于 tsconfig.json 中的 paths,它只是一个别名,指向 ../common/src/foo。这非常棒,在开发中可以使用 nodemon.json 中的此脚本:

{
    "watch": ["src", "../common/src"],
    "ext": "ts",
    "ignore": ["src/public"],
    "exec": "ts-node -r tsconfig-paths/register src/index.ts"
  }

问 题 是 我 无 法 在 生 产 模 式 下 使 它 工 作 。
我 使 用 tsc 构建 项 目 , 如 果 我 检 查 产 生 的 文 件 , 它 们 从 @common/ 导 入 内 容 而 不 是 从 ../common/src/。 起 初 我 认 为 这 没 问 题 , 因 为 tsconfig-paths 在 运 行 时 工 作 , 所 以 我 只 需 将 其 包 含 在start脚本中即可:
node -r tsconfig-paths/register dist/index.js

很遗憾,它没有起作用,而且我在控制台中收到了这些“Cannot find module '@common/foo'”错误消息。

问题出在哪里?是我的配置有误吗?


我的package.json(省略了所有不相关的部分):

{
  "main": "index.js",
  "scripts": {
    "start": "cross-env NODE_ENV=prod node dist/index.js",
    "build": "rimraf ./dist/ && cross-env NODE_ENV=prod tsc"
  },
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "@types/express": "^4.17.4",
    "@types/node": "^13.11.0",
    "cross-env": "^6.0.3",
    "rimraf": "^3.0.2",
    "ts-node": "^8.8.2",
    "tsconfig-paths": "^3.9.0",
    "typescript": "^3.8.3"
  }
}

以下是我去除了所有无关部分后的tsconfig.json文件:

{
  "compilerOptions": {
    "module": "commonjs",
    "baseUrl": "./",
    "outDir": "dist",
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "noImplicitAny": false,
    "target": "es6",
    "emitDecoratorMetadata": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "types": [
      "node"
    ],
    "typeRoots": [
      "node_modules/@types"
    ],
    "paths": {
      "@common/*": [
        "../common/src/*"
      ]
    }
  },
  "include": [
    "./src/**/*.ts"
  ],
  "exclude": [
    "./src/dist/"
  ],
  "references": [
    {
      "path": "../common"
    }
  ]
}
4个回答

27

对于仍然卡在这个问题上的人:

node -r ts-node/register/transpile-only -r tsconfig-paths/register dist/index.js

这是你需要做的。


2
它能够运作,但在生产环境中使用ts-node不是一种不好的做法吗? - Specyk
1
2023年更新:您可以使用https://github.com/esbuild-kit/tsx来完成相同的操作,并获得出色的性能奖励。 - hanan hamza
@hananhamza,你应该将你的建议作为正式答案提交,因为这无疑是将TS转译成其他语言的最有效和高效的方法。 - Bartekus

2

这个问题被很多人问到了,在开发环境下,Typescript可以为路径设置别名,但是在生产环境中不行(不要引用我说的话,我只用了一个月)。

为了解决这个问题,我安装了'module-alias',这个包可以在构建后解决路径问题,而不会影响开发。

我正在构建一个Express-js应用程序,并有以下文件:

server.js:

import env from '@env';
import app from './app';

app.listen(env.SERVER_PORT || 3000);

tsconfig.json(相关部分):

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@env": ["path/to/env"]
    }
  }
}

这解决了开发时路径问题,但在使用“tsc”编译后无法解决。为了解决这个问题,我添加了“module-alias”包并进行了以下更改:

server.js:

import './paths';
import env from '@env';
import app from './app';

app.listen(env.SERVER_PORT || 3000);

paths.js

import 'module-alias/register';
import { addAliases } from 'module-alias';

addAliases({
  '@env': `${__dirname}/path/to/env`,
});

这样做可以确保@env在开发运行时和构建后都能解析。 希望对您有所帮助!

0

也尝试使用tsc构建,但由于别名失败了。 在阅读了ts-node作者的评论后,我跳过了构建阶段并在生产中运行

ts-node --transpileOnly -r tsconfig-paths/register src/server.ts

0
如果不想在生产环境中使用 ts-node,可以创建一个新的 js 文件,在运行时映射路径:
// tsconfig-paths.js

const tsConfig = require('./tsconfig.json');
const tsConfigPaths = require('tsconfig-paths');

let { baseUrl, paths } = tsConfig.compilerOptions;

// Replacing "src" by "dist" in typescript paths map
for (path in paths) {
  paths[path] = paths[path].map((path) => path.replace("src", "dist"));
}

tsConfigPaths.register({ baseUrl, paths });

然后将其添加到节点参数中:
// package.json
// ...
  "scripts": {
    "build": "tsc",
    "start": "node -r ./tsconfig-paths.js dist/main.js",
// ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接