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

Why not use tsc instead of esbuild for production build? #1585

Closed
jods4 opened this issue Jan 18, 2021 · 8 comments
Closed

Why not use tsc instead of esbuild for production build? #1585

jods4 opened this issue Jan 18, 2021 · 8 comments

Comments

@jods4
Copy link
Contributor

jods4 commented Jan 18, 2021

The default Vite + Typescript template uses vuedx-typecheck before calling build to typecheck your whole project.
The official doc says you can call tsc --noEmit to the same effect.

Which is good and I want full type checking during my final build.
But it makes me wonder if it's still worth using esbuild to compile Typescript after that.

The main benefit of esbuild is its speed.
This is really great during development, but during build if you fully type-check your project, you've lost most of the speed as tsc had to parse and analyze your whole project. Is it really worth it to not just ask TS to do the last step of emitting code?

If esbuild had no drawback I wouldn't care much. But using esbuild does come with a few drawbacks.

  • Its downlevel codegen is not as complete as Typescript itself.
  • It has a harder time than TS eliding implicit type-only imports.
  • It can't emit const enum properly (a PR is in the works for the non-namespaced case, hopefully that'll work out. Namespaced const enums will never work without type checking).
  • It can't create a .d.ts type definition file if you build a library.

Would it be interesting to make building with tsc an option?

@yyx990803
Copy link
Member

The main reason is code output consistency between dev and prod. Using different TS transforms during dev and prod opens up room for all kinds of subtle issues.

@jods4
Copy link
Contributor Author

jods4 commented Jan 21, 2021

@yyx990803 I thought about this and would like to share two thoughts with you:

(1) Prod is vastly different from dev anyway, and much more so than TS codegen. I won't even list everything but to mention just a few:

  • Bundling changes code, massively so if you do stuff like module hoisting, emulates built-in features such as import.meta, changes the way/order stuff is loaded (who hasn't had issues related to different CSS order in prod vs dev?)...
  • Minifying is a hugely invasive transform, in fact I had to switch from Terser to Esbuild on one of my projects because Terser generated invalid (yes, plain invalid) JS code.
  • Many code, incl. Vue itself, uses defined constants to strip or modify blocks of code.

Testing prod builds is a must anyway and quite frankly, I trust the official TS codegen more than Esbuild.

So I guess what I'm saying is: yes, that opens up the door to subtle differences but given everything that's going on anyway in a production build, I would be OK opting-in to that.

(2) A way to remove the inconsistency is simply to use TSC for dev as well (as an option).
If you use it with transpileOnly and isolatedModules it's quite fast. Sure, not as fast as esbuild, but plenty fast enough for a single-file compile. Today I have large webpack projects working like that, so I have no doubt that with Vite only compiling served files it would be great.

There are benefits here:

  • You can have consistent prod builds with TSC and enjoy stuff like const enum (not in isolatedModules, but in prod).
  • You can use TS plugins (I'm interested in that).
  • You use the official TS. To be honest, I'm a little uneasy with the long term support and the reliability of a full compiler rewrite by one guy.

So let's broaden this issue a bit: would you consider making the TS compiler for both dev and build configurable between esbuild and tsc?

@yyx990803
Copy link
Member

yyx990803 commented Jan 21, 2021

Absolutely not. The perf difference is significant (20~30x). It is ok from a single-file perspective, but in a typical project you can have hundreds of modules. That could be several seconds slower initial page load.

@yyx990803
Copy link
Member

FYI you can totally disable esbuild and write a custom plugin that uses TSC to handle the transpilation. It's just not going to be the default.

@jods4
Copy link
Contributor Author

jods4 commented Jan 21, 2021

FYI you can totally disable esbuild and write a custom plugin that uses TSC to handle the transpilation. It's just not going to be the default.

Interesting but I don't have the bandwidth for that at the moment.

Single-file transform should be very easy (just invoke tsc api with transpileOnly + isolatedModule, right?) but I'm afraid the build mode with full project compilation is a bit more involved.

@jods4
Copy link
Contributor Author

jods4 commented Jan 21, 2021

Speaking of raw speed, it would be nice if the full build could typecheck your project (a slow operation) in parallel to actually building it.

Using vuedx-typecheck & vite build makes the process serial.

Speaking of typechecking in parallel, I think there's a value in typechecking even during dev, but in the background. (don't block anything, report errors later when you're done).

Estrella, kind of an alternative to Vite, does that.
Even good old Webpack + ts-checker does that.

@yyx990803
Copy link
Member

Type checking is only more efficient when it's done as an external system outside of Vite, because Vite is an on demand transform system during dev, shoe-horning typecheck into it just isn't right in the first place.

Nothing prevents you from using something like concurrently or npm-run-all to run Vite and a type checking process in parallel, this can be done for either build or dev. But for many, this is already done by the IDE, so for Vite to do that by default can be wasteful in many cases.

@jods4
Copy link
Contributor Author

jods4 commented Jan 22, 2021

But for many, this is already done by the IDE

Curious here what's the recommended tools / plugins / workflow?

I would assume most Vue devs use VS Code.
VS Code does not perform full project error reporting for TS by default.
It's hidden behind an obscure setting and I doubt most users turn it on.

@github-actions github-actions bot locked and limited conversation to collaborators Jul 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants