Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript path aliases are not supported for .tsx files #1547

Closed
2 of 15 tasks
pkerschbaum opened this issue Feb 27, 2022 · 10 comments
Closed
2 of 15 tasks

TypeScript path aliases are not supported for .tsx files #1547

pkerschbaum opened this issue Feb 27, 2022 · 10 comments

Comments

@pkerschbaum
Copy link
Contributor

pkerschbaum commented Feb 27, 2022

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

NestJS does support tsconfig.json path aliases for .ts files automatically, but it fails for .tsx files.

The reproduction project has the following changes applied to the StackBlitz template:

  • tsconfig.json
    • configured a path alias
    • "jsx" set to "preserve".
  • created a example file src/example/ExampleComponent.tsx which exports a constant ExampleComponent
  • main.ts
    • importing ExampleComponent
    • logging ExampleComponent (just to make sure the import is not eliminated)
    • also changed the import for AppModule to a path alias - that import works.
  • version of @nestjs/* dependencies in package.json set to "8.3.1"

Minimum reproduction code

https://stackblitz.com/edit/nestjs-typescript-starter-p48ucb?file=src%2Fmain.ts

Steps to reproduce

Just run nest start in the reproduction StackBlitz project.

The following error is thrown:

Error: Cannot find module '~/example/ExampleComponent'
Require stack:
- /home/projects/nestjs-typescript-starter-p48ucb/dist/main.js
    at Function.Module._resolveFilename (https://nestjs-typescript-starter-p48ucb.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:194030)
    at Function.Module._load (https://nestjs-typescript-starter-p48ucb.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:191604)
    at Module.require (https://nestjs-typescript-starter-p48ucb.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:194806)
    at i (https://nestjs-typescript-starter-p48ucb.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:349630)
    at _0x4e304d (https://nestjs-typescript-starter-p48ucb.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:15:99674)
    at Object.eval (/home/projects/nestjs-typescript-starter-p48ucb/src/main.ts:3:1)
    at Object.function (https://nestjs-typescript-starter-p48ucb.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:15:100056)
    at Module._compile (https://nestjs-typescript-starter-p48ucb.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:196043)
    at Object.Module._extensions..js (https://nestjs-typescript-starter-p48ucb.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:196398)
    at Module.load (https://nestjs-typescript-starter-p48ucb.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:194488)

Expected behavior

No error.

Package

  • I don't know. Or some 3rd-party package
  • @nestjs/common
  • @nestjs/core
  • @nestjs/microservices
  • @nestjs/platform-express
  • @nestjs/platform-fastify
  • @nestjs/platform-socket.io
  • @nestjs/platform-ws
  • @nestjs/testing
  • @nestjs/websockets
  • Other (see below)

Other package

No response

NestJS version

8.3.1

Packages versions

8.3.1

Node.js version

14.19.0

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

@jmcdo29
Copy link
Member

jmcdo29 commented Feb 27, 2022

Why are you importing a tsx file in a node/server project? Is there something I'm missing here?

@pkerschbaum
Copy link
Contributor Author

The NestJS server I am working on must send emails in some use cases.
I am using React to generate the HTML for those emails (i.e. I use react-dom/server to transform the React templates to HTML).

@kamilmysliwiec kamilmysliwiec transferred this issue from nestjs/nest Feb 28, 2022
@jmcdo29
Copy link
Member

jmcdo29 commented Feb 28, 2022

I was able to find this is because of this line in our tsconfig-paths API call. However, it looks like node by default does not load jsx files, so even if we add the .tsx extension, you'd still need to have more modifications as post steps to your code to be able to import the react file in the fist place.

It might make more sense to be able to pass the file template to your renderer instead of trying to import it. Just my two cents

@pkerschbaum
Copy link
Contributor Author

pkerschbaum commented Feb 28, 2022

The minimal reproduction StackBlitz project I had provided was actually too "minimal": I had "jsx" of tsconfig.json set to "preserve", which would indeed need additional build or runtime tweaks to make the jsx files runnable.
E.g. adding a post-processing step converting the jsx files to executable js files.

I forked the project and modified it little bit so that it is a more realistic example:

  • added dependencies react and react-dom
  • changed jsx in tsconfig.json from preserve to react-jsx
  • changed main.ts so that it renders the ExampleComponent and prints the result using console.log

This is the fork: https://stackblitz.com/edit/nestjs-typescript-starter-ylu6ro?file=src/main.ts

If main.ts uses a relative path to import './example/ExampleComponent', everything works fine. The output on nest start is this:

❯ npm start
$ nest start
<div>TEST</div>
[Nest] 20  - 02/28/2022, 8:42:59 PM     LOG [NestFactory] Starting Nest application...
[Nest] 20  - 02/28/2022, 8:42:59 PM     LOG [InstanceLoader] AppModule dependencies initialized +28ms
[Nest] 20  - 02/28/2022, 8:42:59 PM     LOG [RoutesResolver] AppController {/}: +6ms
[Nest] 20  - 02/28/2022, 8:42:59 PM     LOG [RouterExplorer] Mapped {/, GET} route +3ms
[Nest] 20  - 02/28/2022, 8:42:59 PM     LOG [NestApplication] Nest application successfully started +4ms

But if the import is changed to an absolute path using the path alias, i.e. '~/example/ExampleComponent', there is an error:

❯ npm start
$ nest start
Error: Cannot find module '~/example/ExampleComponent'
Require stack:
- /home/projects/nestjs-typescript-starter-ylu6ro/dist/main.js
    at Function.Module._resolveFilename (https://nestjs-typescript-starter-ylu6ro.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:194030)
    at Function.Module._load (https://nestjs-typescript-starter-ylu6ro.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:191604)
    at Module.require (https://nestjs-typescript-starter-ylu6ro.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:194806)
    at i (https://nestjs-typescript-starter-ylu6ro.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:349630)
    at _0x4e304d (https://nestjs-typescript-starter-ylu6ro.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:15:99674)
    at Object.eval (/home/projects/nestjs-typescript-starter-ylu6ro/src/main.ts:3:1)
    at Object.function (https://nestjs-typescript-starter-ylu6ro.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:15:100056)
    at Module._compile (https://nestjs-typescript-starter-ylu6ro.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:196043)
    at Object.Module._extensions..js (https://nestjs-typescript-starter-ylu6ro.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:196398)
    at Module.load (https://nestjs-typescript-starter-ylu6ro.w.staticblitz.com/blitz.a8f9013f6760f2c4e84edef607d361d3a32b8049.js:6:194488)

Things I also want to note:

  • I've also seen such a setup in action to generate HTML via React and transform it to PDF reports (kind of a "modern" alternative to something like Jasper Reports).

  • I managed to get it to work at my project using a workaround: I replaced nest start by this combination of tsc-watch and tsc-alias:

    {
      /* ... */
      "scripts": {
        /* ... */
        "start": "tsc-watch --onSuccess \"yarn run start:onsuccess\"",
        "start:onsuccess": "tsc-alias && node ./dist/main.js"
      }
    }

@kamilmysliwiec
Copy link
Member

I think this might be actually an upstream issue with the tsconfig-paths package https://github.com/dividab/tsconfig-paths. Can we double-check if the issue occurs in a pure tsc project with tsconfig-paths lib (without Nest)?

@pkerschbaum
Copy link
Contributor Author

I will check if I can reproduce the issue using tsconfig-paths alone (without Nest) 👍

@pkerschbaum
Copy link
Contributor Author

I created a StackBlitz project using tsconfig-paths only (not the programmatic API, but node -r tsconfig-paths/register), I could not reproduce the issue.

I then just dummy patched the line suggested by @jmcdo29 (in the NestJS StackBlitz project I posted before), and it resolves the issue!

Before, when I used the unmodified @nestjs/cli package, the content of ./dist/main.js is this:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@nestjs/core");
const app_module_1 = require("./app.module");
const ExampleComponent_1 = require("~/example/ExampleComponent"); // <-- here is the issue
async function bootstrap() {
    console.log((0, ExampleComponent_1.renderComponent)());
    const app = await core_1.NestFactory.create(app_module_1.AppModule);
    await app.listen(3000);
}
bootstrap();
//# sourceMappingURL=main.js.map

Note that the imports for both app.module and example/ExampleComponent originally had a path alias used in the source file main.ts, but only the require statement for app.module got its path alias replaced by a relative path; the other require statement still contains the ~ character, thus leading to the error.

Once I "patch" the extension .tsx to ./node_modules/@nestjs/cli/lib/compiler/hooks/tsconfig-paths.hook.js, the output is correct and the nestjs app can be started:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@nestjs/core");
const app_module_1 = require("./app.module");
const ExampleComponent_1 = require("./example/ExampleComponent"); // <-- fixed
async function bootstrap() {
    console.log((0, ExampleComponent_1.renderComponent)());
    const app = await core_1.NestFactory.create(app_module_1.AppModule);
    await app.listen(3000);
}
bootstrap();
//# sourceMappingURL=main.js.map

@kamilmysliwiec
Copy link
Member

Would you like to create a PR to update this specific line?

@pkerschbaum
Copy link
Contributor Author

Yes I will create one 👍

@pkerschbaum
Copy link
Contributor Author

Thank you @jmcdo29 and @kamilmysliwiec for helping resolving this fast, nest start is working now in my project as expected 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants