简体   繁体   English

来自 tsconfig.json 的路径在 tsc 之后不起作用

[英]paths from tsconfig.json doesn't work after tsc

In my Express project, I import from paths like @common/foo .在我的 Express 项目中,我从@common/foo类的路径导入。 Thanks to paths in tsconfig.json , it's just an alias to ../common/src/foo .感谢tsconfig.json中的paths ,它只是../common/src/foo的别名。 That's awesome and works in development with this script in nodemon.json :这太棒了,可以在nodemon.json中使用这个脚本进行开发:

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

The problem is that I can't make it work in production mode.问题是我不能让它在生产模式下工作。

I build the project with tsc , and if I inspect the generated files, they import stuff from @common/ and not from ../common/src/ .我用tsc构建项目,如果我检查生成的文件,它们会从@common/而不是从../common/src/导入内容。 At first I thought it's fine, since tsconfig-paths works in runtime, so I just need to include it in the start script as such:起初我认为这很好,因为tsconfig-paths在运行时工作,所以我只需要将它包含在start脚本中,如下所示:

node -r tsconfig-paths/register dist/index.js

Unfortunately it didn't work, and I get those Cannot find module '@common/foo error messages in console.不幸的是它没有用,我在控制台中收到了Cannot find module '@common/foo错误消息。

What's the problem?有什么问题? Did i configured it wrong?我配置错了吗?


My package.json (dropped all irrelevant parts):我的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"
  }
}

My tsconfig.json (dropped all irrelevant parts):我的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"
    }
  ]
}

for anyone still stuck on this:对于仍然坚持这一点的任何人:

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

this is what you need to do.这是你需要做的。

This was asked around in many places, and apparently Typescript can make path aliases for development, but not production (Don't quote me on that, have been working with it for barely a month).这在很多地方都被问到了,显然 Typescript 可以为开发创建路径别名,但不能为生产创建路径别名(不要引用我的话,已经使用它仅仅一个月了)。

To work around that, I installed 'module-alias', a package that solves the path issue after build, without interfering with development.为了解决这个问题,我安装了“module-alias”,一个 package 解决了构建后的路径问题,而不干扰开发。

I was building an Express-js app, and had these files:我正在构建一个 Express-js 应用程序,并拥有以下文件:

server.js: server.js:

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

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

tsconfig.json (relevant parts): tsconfig.json(相关部分):

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

This resolved the path during development runtime, but not after building with 'tsc'.这解决了开发运行时的路径,但不是在使用“tsc”构建之后。 To work around it, I added the 'module-alias' package and did the following changes:为了解决这个问题,我添加了“模块别名”package 并进行了以下更改:

server.js: server.js:

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

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

paths.js路径.js

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

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

This ensured that @env would resolve in both dev runtime and after building.这确保了 @env 在开发运行时和构建后都会解析。 Hope it helps!希望能帮助到你!

Also tried to build with tsc but failed due aliases.还尝试使用 tsc 构建但由于别名而失败。 After reading a comment from the ts-node author, I skip the build phase and run in production阅读 ts-node 作者的评论后,我跳过构建阶段并在生产中运行

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

If you don't want to use ts-node in production environment, you can create a new js file to map your paths at runtime:如果你不想在生产环境中使用 ts-node,你可以在运行时创建一个新的 js 文件到 map 你的路径:

// 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 });

And then add it to the node params:然后将其添加到节点参数:

// package.json
// ...
  "scripts": {
    "build": "tsc",
    "start": "node -r ./tsconfig-paths.js dist/main.js",
// ...

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

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