What does HackerNews think of sucrase?

Super-fast alternative to Babel for when you can target modern JS runtimes

Language: TypeScript

#10 in Compiler
#27 in JavaScript
#10 in TypeScript
One slightly annoying thing about esbuild/swc is that they're faster by literally not being equivalent to Babel. esbuild intentionally does not emit ASTs, and SWC has their own flavor that is not compatible with Babel. Furthermore, both are written in non-JS languages, meaning any sort of plugin system either has to be written in Go/Rust respectively, or suffer massive performance hits from crossing the JS runtime boundary. SWC abandoned plugins in JS for this reason.

The dirty secret is, as Sucrase (https://github.com/alangpierce/sucrase) reveals, just that Babel is slow and the codebase really pays homage to the project name. Simply computing the config for transforms takes dozens of milliseconds on my machine as it does a bunch of filesystem reads.

So esbuild/swc etc. aren't gaining some magical compiled language speedup, they're just... not doing the dumb things that Babel is. Not ragging on Babel here, it's a 7 year old project originally written by a guy fresh out of high school. I bet a ground up rewrite of Babel could accomplish the same.

Sucrase is written in JS and boasts the highest line throughput of any competing transpiler

https://github.com/alangpierce/sucrase

            Time            Speed
Sucrase 0.57 seconds 636975 lines per second

swc 1.19 seconds 304526 lines per second

esbuild 1.45 seconds 248692 lines per second

TypeScript 8.98 seconds 40240 lines per second

Babel 9.18 seconds 39366 lines per second

Sucrase is faster or really close to SWC (see rhe benchmarks https://github.com/alangpierce/sucrase). Everyone still uses Babel because of the transforms.

And yes, Babel can also be made faster if enough effort is dedicated into it. it's not an impossible feat.

Webpack does way more than esbuild, including running a typechecking compiler instead of just transpiling, running compilers able to downlevel emit to ES5 and providing a deep plugin architecture allowing you to hook into any bit you like. But yes, it hasn't been designed with speed in mind - it has been designed for maximum extensibility instead. Its the same reason why Babel is slow compared to sucrase (written in JS, currently faster than SWC and esbuild but doing somewhat less - https://github.com/alangpierce/sucrase)

tsc has in fact been designed with speed in mind (I've been following the project since before it moved to GitHub, which is when they redesigned it for speed). Going beyond 1 order of magnitude performance improvement while implementing the full feature set is highly unlikely.

Sucrase is what you're looking for. When converting to ES6+, it's actually almost 2x as fast as esbuild on a single thread (though slower in aggregate).

As they point out, there's a JIT warmup time. Testing against small projects that don't allow this makes JS transpilers look much worse than they actually are in real-world projects.

https://github.com/alangpierce/sucrase

https://github.com/alangpierce/sucrase/blob/main/benchmark/b...

There is also swc which is fast because... its written in Rust https://swc.rs/

But there is also sucrase which is fast because.. its written in TypeScript? https://github.com/alangpierce/sucrase

Even if your target platform didn't have ES6 modules, Babel is probably not the tool you'd want to transpile those with. Let the bundler (which is the topic of the discussion here so I assume a bundler is used) handle them. Tree shaking works better that way anyway.

Also if JSX or similar JS extensions are the only thing you need tramspiling for, you might want to look at Sucrase [1] as a fast alternative to Babel.

https://github.com/alangpierce/sucrase

> I would say the primary motivators at this point have shifted from browser compatibility to syntaxes like TypeScript and JSX that will (likely) never be supported natively

I suggest using a single-pass transpiler like Surcase[0] that doesn't translate to IE11-compatible syntax, and just loops through the string once, avoiding generating an AST– making it much faster– removing TypeScript annotations and desugaring JSX.

If you additionally need to support IE11, you can use a development build with Surcase and a production build with a bundler like Snowpack. C/C++ developers have been doing things like this for ages: compiling files as objects during development, and compiling them into one big binary for production.

[0]: https://github.com/alangpierce/sucrase

Here's my suggestion if you want faster builds:

In development, use an index.html that loads it directly from the filesystem, using a single-pass annotation remover such as https://github.com/alangpierce/sucrase A single-pass transpiler doesn't build an AST, instead just looping over everything once, which will surely make it faster than esbuild.

In production, use a bundler like snowpack.

I think that’s the point. No plugin system. Compare Babel to Bublé or even Sucrase for example: https://github.com/alangpierce/sucrase

Preparing data for external use always takes extra effort.

You can build an efficient self-contained tool in JavaScript too.

I'd love to see Sucrase (https://github.com/alangpierce/sucrase) included in the performance comparison.
For those worried about compile time for large projects, tools like https://github.com/alangpierce/sucrase can go a long way for the transpilation (remove types), while you can use the TypeScript compiler in parallel only for the type analysis.

That said, Sucrase has a number of issues still. Nothing that can't be resolved, but enough to prevent me from using it in a few projects.

I've been working on a very similar tool, interesting to see some competition. :-)

https://github.com/alangpierce/sucrase

In my case, it's still running as JS, but rearchitected to solve the more straightforward problem where you don't need to compile to ES5. I've thought about rewriting it in Rust to see how much faster it gets, though currently I'm trying to get it running in WebAssembly via AssemblyScript ( https://github.com/AssemblyScript/assemblyscript ), which has been promising.

I'm curious about the about the Babel performance comparison. Benchmarking JS is tricky because, from my observations, the performance improves by a factor of ~20 if you give it 5-10 seconds for the JIT to fully optimize everything. https://github.com/alangpierce/sucrase/issues/216 . Rust and WebAssembly both have a significant advantage in that sense when running on small datasets.

I haven't looked too much into the TypeScript compiler implementation, but my theory is they've just had more bandwidth to do little optimizations or maybe got lucky on some design decisions rather than it being something fundamental. To be clear, this doesn't include any typechecking, so Babel and TypeScript are pretty much solving the same problem here.

I've actually been hacking on a faster alternative to babel/tsc for simple use cases: https://github.com/alangpierce/sucrase . It has a built-in benchmark (`yarn run benchmark`) with at least one example of where typescript is about 3x faster. So you could look at that config if you want one example to compare the two.