egoist / tsup

The simplest and fastest way to bundle your TypeScript libraries.
https://tsup.egoist.dev
MIT License
9.24k stars 218 forks source link

`dts` creation impossibly slow. #945

Open datner opened 1 year ago

datner commented 1 year ago

I've been trying to migrate some project from unbuild to tsup. Theres nothing special about it, it's not that big either.

unbuild was pretty fast, with 2-3s to chew the whole thing. dts included. I've moved to tsup. bundling was amazingly fast, less than 60ms. But dts takes 5 seconds. I do not resolve, it's a plain dts: true.

I've looked at the rollup-plugin-dts and saw that they the following:

The plugin works best with already existing .d.ts files generated by the typescript compiler from idiomatic code.

Ok, so lets do that. I run tsc with declaration: true, without a declaration map. It takes around 1s and done. Now tsup takes around 20s to run dts before saying it's out of memory.

I thought there might be some multiple entry points shenanigans, so I tried reducing to only 1 entry point. dts with no prior tsc - 1s. Relatively slow, but fine. dts with tsc - crash after 20s. OOM. dts with tsc only on the entry file - now dts takes 11s but resolves.... with the same exact result as it would if I haven't generated the d.ts beforehand.

How can this be? Why would it make things worse?? How can unbuild do it so fast with the same exact plugin, less optimized??? (they don't disable anything like tsup does)

I know this is a general typescript issue, but somehow tsup turns a slow operation into a full-on odyssey. Possibly related issues: #840

I tried to work on this on my own, but I couldn't find the source of the issue.

Upvote & Fund

Fund with Polar

coopbri commented 1 year ago

Hey @datner, did you ever find a solution to this? I am encountering the same issue now that my project has reached a certain size and too am running into a (flaky, but always slow) out-of-memory error when enabling .d.ts generation via tsup.

datner commented 1 year ago

@coopbri I have not, I went down a rabbit hole of horrors and became a tsc hermit. I no longer wish to fight with bundling. I now use the vanilla tsc compiler for all my libs, only reaching for a simple babel transpilation step if I need to have both esm and cjs, like seen in this repo or a simple rollup config. I write my code in such a way that it's completely tree-shakeable and only need to work with my main app(s) bundlers which are a pain enough. Funny enough, my builds now take 1-2s and have a smaller size after tree shaking, so it's a win

One day the pain will go away....

coopbri commented 1 year ago

Haha, no worries man! Thanks for detailing your process. I think I'll do much of the same for now (tsc hermit as you eloquently put :smile:).

datner commented 1 year ago

@coopbri word of advice, set up self-imports if you want to bundle to esm and cjs since esm requires you used named imports or full paths (with extensions ) and cjs wants named imports and forbids extensions

import * as Foo from './Foo.js' // <-- breaks cjs
import * as Foo from './Foo' // <-- breaks esm
import * as Foo from "my-lib/Foo" // works for both
coopbri commented 1 year ago

Geat tip! Thank you!!

coopbri commented 1 year ago

@datner you may have seen this already, but I'm keeping a close eye on it: https://github.com/dudykr/stc (some discussion at https://github.com/swc-project/swc/issues/657)

As an avid SWC fan, I'm really excited for this!

datner commented 1 year ago

@coopbri I'm quite satisfied with the performance of tsc surprisingly. But a better tsserver, especially one that actually conforms to the lsp protocol, is something I yearn for.

That said, I also like swc and have seen this project. It has nothing to see so I didn't know it was usable, I'll give it another glance. Thanks!

maelp commented 11 months ago

I have the same issue, dts does an out-of-memory, although it's a quite simple expressjs server where tsc has no issue generating types...

tysonclugg commented 5 months ago

This might be somewhat related to https://github.com/egoist/tsup/issues/920#issuecomment-2159611615 and may have been fixed upstream in Node v21 and above, particularly if the heap was allocated using slower memory pages from swap. Can someone please test and confirm if this is the case?