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

Allow disabling type-checking when swc-loader is used #2833

Open
3 of 15 tasks
christian-gama opened this issue Dec 2, 2024 · 12 comments
Open
3 of 15 tasks

Allow disabling type-checking when swc-loader is used #2833

christian-gama opened this issue Dec 2, 2024 · 12 comments

Comments

@christian-gama
Copy link

christian-gama commented Dec 2, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

I have a monorepo project that uses webpack + swc-loader + @nestjs/swagger plugin. Everything runs fine and fast (build is around 100ms), however if I simply REMOVE the @nestjs/swagger plugin, build time increases to ~=2200ms for no reason.

Screenshot 2024-12-04 at 09 01 42 Screenshot 2024-12-04 at 09 15 06

Minimum reproduction code

https://github.com/christian-gama/nestjs-build-bug-reproduction

Steps to reproduce

Local

  1. Run git clone https://github.com/christian-gama/nestjs-build-bug-reproduction.git
  2. Run cd nestjs-build-bug-reproduction.git
  3. Run pnpm install
  4. Run chmod +x ./entrypoint.sh
  5. Run ./entrypoint.sh
  6. Compare the build time with plugin enabled and plugin disabled

Docker

  1. Run git clone https://github.com/christian-gama/nestjs-build-bug-reproduction.git
  2. Run cd nestjs-build-bug-reproduction.git
  3. Run pnpm docker:build
  4. Compare the build time with plugin enabled and plugin disabled

Expected behavior

Disabling or enabling the @nestjs/swagger should have no impact in the build time of the application, but the weirdest behavior is to have a build time 10x faster with the plugin ENABLED, which does not make any sense, since swc-loader does not even support the @nest/swagger plugin.

I'd like to see a faster build time without using the @nest/swagger plugin enabled - the only thing this plugin is doing for the project is to improve the build time, which shouldn't be happening.

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

@nestjs/swagger

NestJS version

10.4.12

Packages versions

[System Information]
OS Version : macOS 24.1.0
NodeJS Version : v23.1.0
NPM Version : 10.9.0

[Nest CLI]
Nest CLI Version : 10.4.8

[Nest Platform Information]
platform-express version : 10.4.12
cache-manager version : 2.3.0
microservices version : 10.4.12
mapped-types version : 2.0.6
schematics version : 10.2.3
passport version : 10.0.3
schedule version : 4.1.1
terminus version : 10.2.3
swagger version : 8.0.7
testing version : 10.4.12
common version : 10.4.12
config version : 3.3.0
axios version : 3.1.2
core version : 10.4.12
cli version : 10.4.8
version : 2.4.2
version : 1.2.4

Node.js version

23.1.0

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

@micalevisk
Copy link
Member

Disabling the plugin should have no impact on the build time.

but the plugins are evaluated by @nestjs/cli when you use the build command. And so they should impact the build time.

The only problem that I can see is the performance of this task

@christian-gama
Copy link
Author

christian-gama commented Dec 2, 2024

Disabling the plugin should have no impact on the build time.

but the plugins are evaluated by @nestjs/cli when you use the build command. And so they should impact the build time.

The only problem that I can see is the performance of this task

I mean, adding the plugin should not improve performance - it should at most have the same performance or a worse performance. Does not make sense enabling @nestjs/swagger plugin and simply getting 15x faster build time.

What if I want to have this 15x faster build in my project and opt to not use the swagger plugin? Currently is not possible.

@kamilmysliwiec
Copy link
Member

Enabling the plugin doesn't make the build faster as you can't even use it with swc-loader (they are not compatible). I suppose it just doesn't build stuff at all (or fallbacks to cache)

Please provide a minimum reproduction repository (Git repository/StackBlitz/CodeSandbox project).

@christian-gama
Copy link
Author

Enabling the plugin doesn't make the build faster as you can't even use it with swc-loader (they are not compatible). I suppose it just doesn't build stuff at all (or fallbacks to cache)

Please provide a minimum reproduction repository (Git repository/StackBlitz/CodeSandbox project).

It's not caching at all and I am sure it's building correctly, because in both scenarios application runs correctly. I am sure it's not caching because I build it in a docker container as well and the behavior is the same.

I'll try to create a repository that reproduces that, but I am afraid that a small repository won't be noticeable the difference in build time.

@kamilmysliwiec
Copy link
Member

Either way, @nestjs/swagger plugin is not compatible with swc-loader so it's not the plugin that causes this issue (it's not even being executed in this case).

We need a minimum reproduction repository to help you out

@christian-gama
Copy link
Author

Either way, @nestjs/swagger plugin is not compatible with swc-loader so it's not the plugin that causes this issue (it's not even being executed in this case).

We need a minimum reproduction repository to help you out

Done! Here is the repository.
https://github.com/christian-gama/nestjs-build-bug-reproduction

You can follow the README.md, but in short I have created an entrypoint script that builds the application with the @nestjs/swagger plugin enabled and also with the plugin disabled so that you can easily compare the build time between them. I recommend running it in Docker pnpm docker:build and check the output, but both in docker or locally the behavior is the same.

You can of course reproduce without the script by simple running the build commands manually and comparing the time, having full control of the flow.

There is also a README.md with the instructions to reproduce it, but it's quite straightforward to reproduce this weird behavior.

As you can see in the screenshot, enabling the @nestjs/swagger plugin improves the build time by ~15x, which is weird. What if I want fast build times without this plugin enabled? Currently is not possible, so I am forced to use this plugin to improve the build time.

image

@kamilmysliwiec kamilmysliwiec transferred this issue from nestjs/nest Dec 4, 2024
@kamilmysliwiec
Copy link
Member

kamilmysliwiec commented Dec 4, 2024

I'll look into it as soon as I can, but it has low priority as—as I've already mentioned above—plugin and swc-loader are not compatible anyway, so the results you're seeing are incorrect (there's very likely some error being thrown under the hood that falls back to a different configuration—a plugin entry in the configuration might be causing it, but I'll have to double-check).

TLDR; It's not swc-loader "without a plugin causing the build to be slow" (as it doesn't even use that plugin). There must be something else

@kamilmysliwiec
Copy link
Member

kamilmysliwiec commented Dec 4, 2024

Alright, I had a few minutes and decided to dive deeper into this issue.

The difference is, when a project doesn't use any plugin, we can run the fork-ts-checker-webpack-plugin (https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) package to verify TS types in parallel (while TS/SWC itself just transpiles your code without performing any type checking). However, if you have at least 1 plugin registered, then we can't use that package and we need to rely on TSC (or one of the NestJS CLI plugins themselves).

That being said, in your repository npm run build-with-plugin command does not perform any type-checking (it just transpiles your code). For example, if you change app.listen to app.random it won't even fail (your build will succeed) - that's why it's "faster". On the other hand, if you run npm run build-without-plugin you'll see errors:

image

Hence 3 seconds instead of 400ms

Using swc-loader + plugins (which isn't supported, as mentioned above, and shouldn't be used) means there's no async type-checker + SWC just transpiles your code (no errors) + plugins are not executed anyway.

@christian-gama
Copy link
Author

Alright, I had a few minutes and decided to dive deeper into this issue.

The difference is, when a project doesn't use any plugin, we can run the fork-ts-checker-webpack-plugin (https://github.com/TypeStrong/fork-ts-checker-webpack-plugin) package to verify TS types in parallel (while TS/SWC itself just transpiles your code without performing any type checking). However, if you have at least 1 plugin registered, then we can't use that package and we need to rely on TSC (or one of the NestJS CLI plugins themselves).

That being said, in your repository npm run build-with-plugin command does not perform any type-checking (it just transpiles your code). For example, if you change app.listen to app.random it won't even fail (your build will succeed) - that's why it's "faster". On the other hand, if you run npm run build-without-plugin you'll see errors:

image

Hence 3 seconds instead of 400ms

Using swc-loader + plugins (which isn't supported, as mentioned above, and shouldn't be used) means there's no async type-checker + SWC just transpiles your code (no errors) + plugins are not executed anyway.

Sure, makes sense. But how can I have no type-check in my build without the need of enabling a plugin while using webpack + swc-loader? I'd like to prioritize a faster build instead.

@kamilmysliwiec
Copy link
Member

Why would you ever want npm run build to run without a type-checker? For --watch mode you won't see much of a difference anyway

@kamilmysliwiec kamilmysliwiec changed the title Build time up to 15x slower when REMOVING the @nestjs/swagger plugin from nest-cli.json Allow disabling type-checking when swc-loader is used Dec 4, 2024
@christian-gama
Copy link
Author

christian-gama commented Dec 4, 2024

Why would you ever want npm run build to run without a type-checker? For --watch mode you won't see much of a difference anyway

I've been trying to create a NestJS project using Bun and sometimes I got a different behavior using bun --bun nest start than running the application directly from build, so I was developing relying on bun nest build --watch and bun --bun --watch dist/main.js, which always gave me the correct and expected behavior. Having a long build time and having to wait a few seconds for every minor change that I made is painful, thats why I'd like to have an option to disable typecheck without adding a random plugin that disables the typecheck.

Besides, I've just tested and running nest start --watch have typecheck enabled as well, making me wait a considerable time for each minor change.

@kamilmysliwiec
Copy link
Member

const swcDefaultConfig =
  require('@nestjs/cli/lib/compiler/defaults/swc-defaults').swcDefaultsFactory()
    .swcOptions;

module.exports = (webpackConfig) => {
  return {
    module: {
      rules: [
        {
          test: /\.ts$/,
          exclude: /node_modules/,
          use: {
            loader: 'swc-loader',
            options: swcDefaultConfig,
          },
        },
      ],
    },
    plugins: [webpackConfig.plugins[0]],
  };
};

image

☝️ this configuration excludes ForkTsCheckerPlugin

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