esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

[Feature] add esbuild/register

Open aelbore opened this issue 5 years ago • 10 comments

  • this is same as ts-node/register
  • run typescript without compilation/transpilation
  • this could be useful if you are have a unit test thats written in typescript
  • for reference https://github.com/TypeStrong/ts-node
  • another use case is developing node app using typescript

aelbore avatar May 26 '20 13:05 aelbore

I could see having something like this, although if it's non-trivial it's probably better as an independent 3rd-party package. Keep in mind that esbuild doesn't do type checking, so if you want type checking you'd still have to invoke the TypeScript compiler API. Also, I assume this is somewhat blocked on #136 unless you want to run execFileSync every time (which should be fine for smaller projects).

evanw avatar May 27 '20 05:05 evanw

Update: there is now a transformSync() API function, so this should be pretty easy to implement. It would be interesting to see someone experiment with a 3rd-party package that does this.

evanw avatar Jun 11 '20 08:06 evanw

Referencing https://github.com/egoist/esbuild-register which works with esbuild but still need esm.

node -r esm -r esbuild-register file.ts works like ts-node file.ts for scripting purposes.

esbuild is incredible, the speed difference is quite noticeable.

Hebilicious avatar Jul 26 '20 18:07 Hebilicious

I was looking at this too – there's one unfortunate downside to esbuild being a separate process which is that require needs to resolve synchronously – so each compilation ends up being a process invocation.

I looked into some potential ways around this – here are a couple of modules that could potentially enable synchronous communication with a persistent esbuild server process:

  • https://github.com/MMhunter/node-sync-ipc
  • https://github.com/JacobFischer/netlinkwrapper

I haven't looked any deeper into this, but I'd be interested to see if it could be achieved without the overhead of a process invocation each time

mhart avatar Oct 03 '20 17:10 mhart

The sync IPC approach is interesting. FYI someone has tried a different approach here in case you want to look at that too: #248.

I also wanted to say that this isn't what esbuild was designed to do, so I think it's ok that esbuild is not a perfect fit for this particular problem.

evanw avatar Oct 04 '20 07:10 evanw

Yeah, I wasn't trying to suggest it was esbuild's responsibility in any way – kinda surprised after all this time that Node.js doesn't have better sync primitives for communicating with processes. If spawnSync/execSync are fine, then why not?

mhart avatar Oct 04 '20 13:10 mhart

I've just released ts-eager – which has a require hook (as well as a binary wrapper).

It's a little similar to esbuild-register, but it does eager compilation up-front of all files specified in your tsconfig.json (or specified tsconfig file). This works a lot faster for large projects compared with synchronous on-demand-compilation.

It also falls back to ts-node for emitDecoratorMetadata support, as this is unsupported by esbuild

mhart avatar Oct 13 '20 15:10 mhart

Can we not use the wasm version of esbuild for register so there is no extra process invocation penalty ?

nojvek avatar Apr 03 '21 17:04 nojvek

The WASM version should be avoided if possible due to the huge performance overhead of node's WebAssembly implementation. The native version will always be much faster than the WASM version.

There is now an experimental optimized transformSync call that is active when the ESBUILD_WORKER_THREADS environment variable is present. It runs esbuild in a worker thread and then uses atomics to block the main thread to stay synchronous. If it ends up working well, it could become the default behavior in the future.

Can you try running your code with ESBUILD_WORKER_THREADS=1 and report back a) whether it works at all and b) what the performance difference is?

evanw avatar Apr 03 '21 19:04 evanw

If there's interest, tsx offers a Node API:

  • tsx/cjs/api for CommonJS context

    • register()
    • require()
  • tsx/esm/api for Module context

    • register()
    • tsImport()

privatenumber avatar May 07 '24 04:05 privatenumber