Bun hype. How we learned nothing from Yarn
Tags: bunjs, javascript, node, npm
Published: 2023-09-16 02:10:39

Here we go again, making the same mistake. I'm constantly reminded that every 5 years the amount of programmers in the world doubles, which means at any point, 50% of the industry has less than 5 years experience. Which is probably why we keep falling for stuff like Bun. But I've seen this movie before, and I know how it ends.


* * *


## Part one - The story of Yarn

I see a lot of parallels between Yarn and Bun. Both targeted existing open source systems, and instead of actually contributing to them, just went off to create their own competing technology. Both sold themselves on being way faster. Both went in with the goal of splitting the ecosystem. Neither had good backwards compatibility support. And both announced that they were officially v1.0 and ready for production! *...while not actually supporting Windows* (read: not actually remotely production ready).

So what happened to Yarn? Well, they came out with about a dozen cool new features that npm didn't have. And they were many times faster than npm. But then... only a year later, npm was already faster than Yarn. And another year later, Yarn would create a blog post explaining how it would ultimately be impossible for them to ever be faster than npm, due to the npm CLI being created by the same people in charge of the npm servers where the packages were stored and downloaded from. And that is still true to this day. In 2023, npm is still faster than Yarn. Its original big selling point.... has not been relevant for 5 years.

But what about the other features Yarn offered? With each passing year, more and more of them were implemented and released in npm, and as of today, **all** of the formerly-unique features Yarn offered, are built in to npm. Sure the implementations of the features are slightly different and for those that really care about the subtle nuance between how Yarn, Lerna, Turbo, and npm handle mono-repo management, you may prefer one over the other. But for the vast majority of use cases, the way npm implements these features is perfectly fine for almost all users.

Ah, but Bun is surely different? Right? I mean, it's written with *ZIG!* And *ZIG!* is super fast.... right? Eh, not really. It isn't doing anything magical, ultimately any performance you can achieve with it could be achieved with C++ (what Node.js is written in). So, just like with the story of old slow npm, once performance was prioritized, npm was able to go just as fast (faster even) than the competition. I can see a similar thing happening with Node. If given the proper attention, roughly equivalent speeds should be possible to the point where the differences are negligible. Well... kinda. I mean, we should probably acknowledge the fact that some of the benchmarks Bun brags about are cherry-picked or [misrepresentative](https://twitter.com/youyuxi/status/1701243750666703338). So, even Bun doesn't live up to its own marketing hype. But you get the point.

Back to the parable of Yarn. When Yarn came out, it *said* it supported Windows. But none of the Facebook developers working on Yarn used Windows for their primary OS. So they quickly found out that Yarn, in fact *did not* run on that platform when released.

> *A short aside:* Hi there, Primagen (the rest of you can skip this). Now I know, you've already made a snarky comment about Windows. But perhaps you should try to *really* value diversity in our society, and accept different ways of life. I mean, I get it. I totally do, Windows users make up a very very tiny minority of only 90% of computer users. But maybe... we should be respectful of that barely noticeable minority. :)
> Back to the story.

So after about 2 weeks or so, they finally "fixed" it and Yarn could install and run on Windows.... kinda. I actually was never able to get Yarn to run reliably on Windows myself until they switched over to using `corepack`. Once you could install `corepack` via npm, and then install Yarn (or pnpm) on top of it, it was finally Windows compatible in a reliable, non-buggy, non-crashing, way. But by that point, Facebook had already dropped Yarn, and slowly, so did everyone else, it was already dying off by the time it ran on Windows. 

I've still, to this day, never been able to get a Yarn mono-repo to run on Windows. I'm convinced it is not possible. Anyone who says they got it to work is lying to you. Sure, maybe in some Windows VM with nothing installed (not even Windows Updates), *maybe* someone got a Yarn monorepo to run on Windows, for a few glorious seconds. And maybe they also saw Sasquatch in the woods. Anything can happen. But on a *real* developer laptop, with random shit in the PATH, and Node and nvm-windows and volta and who knows what other random things installed, no, it doesn't work.

Okay, so Yarn came around, forced npm to get better, and then died. What's the problem? If that's all it did, then Yarn would have been great, but sadly it wasn't. npm was focused on developing and releasing the features the vast majority of users needed. But Yarn was focused on the features *Facebook* needed. Many of which were not important for 99% of people using npm. However, once people started using Yarn, npm had to repriortize what features they would develop and release. Instead of delivering higher value features that would be more relevant to more users, they had to quickly play catch up and add equivalent features to what Yarn was offering, as to avoid a split in the ecosystem. But Yarn marketed itself very well, and people bought into the hype. Even I was hyped for Yarn when it came out, until I found out it didn't actually run on Windows. But others didn't realize, or didn't care about that, and adopted it... and... and...

... And then Yarn became tribal. Stupid humans. Everything has to become tribal. And for several years there were thousands of README's created on projects that *only* told you the Yarn instructions for how to install the project. Confusing new developers. I can't tell you the amount of junior devs that have come to me asking for clarification on what this "Yarn thing" is, and if they need it. Thinking the project(s) they found would *only* work with Yarn. What a waste of everyone's time and mental space.

I always assumed someone at Facebook just found that convincing their boss to let them spend time adding features to an open source project they couldn't take credit for was a hard sell. It was probably easier for them to get approval to work on these features if they could use it for marketing for job recruitment or something. It always smelled of [Not Invented Here syndrome](https://en.wikipedia.org/wiki/Not_invented_here).

Had Facebook just contributed to npm the features they wanted, then their features would have been released *along side* the ones npm was already working on. But instead it delayed the release of these other features by many years, resulting in duplicated efforts. And all for what? Yarn is basically dead at this point, except for a few niche edge cases. But I haven't seen a `yarn add` in a README in the past year or two. It's a sign of a past era.


* * *


## Part two - Bun is actually much worse

Unlike Yarn, which offered speed and a dozen new features, Bun offers speed and like 3 new features. Let's briefly go over them.

1. Macros - Used during a build process. They've been called a mistake by some. My biggest concern is that your build process is now stuck with Bun. You can't switch to something else unless it has an equivalent macro system, or you re-write your build process. You're opting into future tech debt.
1. `bun.x` APIs - These are new API's that do literally the same thing the Node.js APIs do, "but faster". This is worse than the macros because now your code is a Bun virus. If I `npm install` your package and run it in Node, I'll get `ReferenceError: Bun is not defined` when trying to use your library. Forcing all users of your library to adopt Bun. This is another forced split of the ecosystem, similar to what Yarn was doing, but much worse.
   * I could maybe see some wrapper library you import that checks if `bun` exists and if so it uses the faster API and if not it falls back to Node. If Bun gets remotely popular I imagine this would be very common. But that's just one more dependency to maintain in your project, which sort of defeats the point of an "all in one" system that lets you skip having tooling dependencies if everyone that uses it has to install additional tooling libraries to make it easier to use.
1. Meta-language support - Should Node.js have the Vue-Template-Compiler built in? It sounds absolutely insane to ask that. What about Markdown, or Sass, or CoffeeScript? Yeah, that would be pretty stupid for the main platform that everything is built on top of to just build in. It would feel very short-sighted.
   * Meta-languages exist to fill in a gap in the original languages, they are by their nature impermanent and flexible. They're like adding really good suspension to your car as your drive over the potholes in the original language. Until the original language can come by and fill the potholes. There is a reason we don't use CoffeeScript anymore, most of the features it offered were added into the language in ES6. CSS has slowly added "good enough" equivalents to a few high value Sass features, and we've seen the first decline in Sass usage *ever* afterwards. But here we are with the worst templating system, JSX and the most contentious of all frontend tooling, TypeScript built in to Bun.
   * TypeScript's usage plateaued around 2020 (at a little over a 3rd of the JS ecosystem having adopted it), and in the past year finally showing its first signs of decline as it is replaced with better, simpler alternatives like `eslint-plugin-jsdocs` ([get started here](https://github.com/tjw-lint/eslint-config-tjw-import#using-this)), and a potential comment based ES202X official type system that will likely lead to a rapid decline in the need for creating `.ts` files. With these potholes filled, TypeScript will need to either find new potholes to try to smooth out and justify it's existence, or accept that it's job is done and slowly fade away. Never actually dying, the same way CoffeeScript is still technically around, but ultimately being another sign of an older era. Like all the other once-useful technologies we've evolved beyond the utility of (LESS, Stylus, Sass, CoffeeScript, Yarn, Grunt, etc.).
   * Sass is a great example. It was at one point [used by ~96% of frontend devs and had an over 90% satisfaction rate](https://i.imgur.com/cEo358S.png) (*State of CSS 2019*). But has dropped in usage and satisfaction as the Meta-Language's API evolved to become much more complex in order to solve more complex problems. It is no longer focused on being the dead-simple tool for everyone, and is now focused on being a very advanced tool for people doing very advanced things. A much more niche use.
   * I keep wondering what weird mishmash of technologies Bun would have been made out of it it came out in a previous year, and what weird legacy code they would be stuck maintaining today. If it came out in 2019 at the peak of Sass, used by basically everyone, it would totally make sense as a candidate to build into Bun right? But then what do you do when all of the Sass API's change and the old import system is completely deprecated? Normally you'd just `npm install` the version of Sass you need for your project, and pin the old version if that's what your code worked with and you don't want to upgrade. But if you were using Bun for this, and then you come back to it a few years later and now the project just won't build because the Sass version in Bun isn't compatible with the Sass code you wrote, you need to spend a day trying to figure out what version your code actually needs and manually installing the correct version of Sass to get your project to run again. That's why it would be insane to build a meta-language into Node.js, or by extension, Bun. But that's what they've done, and I forsee pain in the future for those that rely heavily on it instead of as a simple quick convenience.

That last one, built-in meta-languages, sort of leans into what Bun *really* is. It's just an abstraction layer for a bunch of technologies. It isn't an actual alternative, or competitor, it's literally the same thing, just already built in. Which sounds nice on paper, but ultimately is pretty bad.

Abstractions can be great, and simplify things. Let's look at Webpack for example. Webpack is... well just awful. NO ONE likes dealing with it. And that's why every JS Framework had to build an abstraction layer for it, because no wants to touch Webpack. Like the Angular-CLI, or Create-React-App, or Svelte-CLI, or the phenomenal Vue-CLI (which even has a GUI). We'll use Vue as the example, since it did the best job out of all of these abstractions. The `vue.config.js` file was a simple config that abstracted away all of the complexity of Webpack, while still giving you the exact same level of control if you needed it. It also reduced the amount of dependencies down from around 30-ish to like 3-ish. But then Vue's creator, Evan You, went and made Vite. And the `vite.config.js` was basically the same exact level of complexity as the `vue.config.js` except it didn't require them to maintain an entirely separate project (the Vue-CLI) to make it that way. Switching from Vue-CLI over to Vite, I ended up with the same amount of dependencies, and the same amount of config code. The end result is Vite is an abstraction layer for ESBuild that is as easy to use as the best abstraction layer for what it was replacing.

But Bun isn't doing that. It isn't taking something hard, and making a simpler abstraction for it. It's taking ESBuild and abstracting it just like how Vite is. It's not an improvement, it's basically the same thing. This is also the case for unit tests. Where they don't even pretend to offer something new, instead telling you to write your code as Jest or Vitest like normal, and they'll just hijack the imports and replace them with their own faster code under the hood.

Bun is just an abstraction layer on top of the tools we already have. Meaning it will always be behind the curve and can introduce additional bugs at that layer. Not ideal for such **mission critical systems** like **installing dependencies**, **testing code**, and **building the code to be sent to production**.

But we haven't even gotten to the two worst things Bun does, and the really scary parts.


### Windows

I picked on Yarn for it's poor Windows support. But they look amazing compared to Bun. At least they *kind of* had Windows support when they released it. It only barely worked some of the time, but it was there. However, of the dozens of features that Bun brags about, **not even one of them** is supported on Windows when it was released as "version 1.0".

> "The Windows build is highly experimental and not production-ready. Only the JavaScript runtime is enabled; the package manager, test runner, and bundler have been disabled. Performance is not optimized." - Official Bun 1.0 blog post

So imagine this, they just launched and are showing off all these cool features that they are excited about and want people to use. What is more likely to happen? As thousands of people start using it and giving feedback, finding bugs, requesting features, needing support, do you think they will:

**A.** Completely ignore all of the new users for the next year and focus solely on getting complete feature parity and making a polished, rock-solid, reliable, ultra-fast, Windows compatible build. Likely killing off any momentum they built from their initial hype-cycle, and maybe even losing them the VC funding they've been living off of.  
**B.** Focus almost all of their very small team's efforts on keeping their existing user's happy by improving the Linux/OSX versions that already mostly work so that the product *looks* well maintained and can slowly gain adoption within those communities, while being virally spread by tribal developers intentionally creating non-portable code, knowing that it will not work in Node, or even on Windows.

I genuinely believe they have every intent on getting a Windows version up and working. I just do not believe for a second that a year after 1.0 is released that they will have feature parity in the Windows version. ***Maybe*** the Windows version will have feature parity with version 1.0 by then, but I doubt they will be stopping all work on the Linux version for a year. At that point the two flavors of Bun will be out of sync with each other, leading to confusion.

This leads us into the biggest missing feature of Bun.


## There is no Bun Version Manager

Of all the tools they put into Bun, the one tool they didn't build in is a version manager. That is INSANE to me. I think it's actually insane that Node.js doesn't have a version manager built in. Let's break this down. On Node.js I have:

* `nvm` - Which mostly works fine on linux/osx, but has some annoyances.
* `nodist` - Which is great, but only works on older versions of Windows.
* `nvm-windows` - For newer Windows versions, but barely works and is buggy as hell.
* `volta` - Which has the worst API of all of them, but is also the most stable and reliable and runs on all OS's, even really old versions of Windows.

Why do I have to know about these 4 tools? This is stupid. But what's considerably worse than having to deal with 4 tools that do the same thing is just not having **any tool** at all.

Node.js is **WAY** more focused on backwards compatibility than Bun is. But as time has gone on, even Node has deprecated parts of their API. Many times this is a result of the V8 engine itself deprecating features. Node.js is actually involved somewhat in the direction of V8 at this point, and even with having some level of input, it isn't possible for them to avoid all breaking changes and deprecations, leading to old Node.js code straight up not working on newer versions of Node.

So I don't believe for a second that Bun got everything right on the first try, and nothing about it will change over time, and all code you write in it, will always work forever. Especially since they are inheriting whatever deprecations will come with the Apple Webkit JS engine they are using.

What about a year from now when Bun 1.8 on Linux is out, but Windows just hits 1.0. Where I work, the devs on my team use different OS's (Linux, OSX, Windows). If we can't freely switch between versions of bun, then our Linux user's won't be able to downgrade to version 1.0 so we are all working with the same features (generously assuming a Windows version is released by then).

We as web developers used Grunt for our build tooling. Then Gulp came out and made the process simpler and we switched over to it. Then Gulp 4 came out and completely changed the API and no one wanted to deal with that so we switched to npm scripts for our basic build automation. But then we wanted actual bundling abilities and tree shaking. So we, as an entire JS community, switched to Webpack (or more accurately, abstractions on top of it). But Webpack was slow and annoying, so when Vite came out we all switched over to it.

But ya know what? I'm not *in love* with Vite. Is it the best thing right now? Yeah it is. But there are things about it I wish were better. And over the coming years more and more of those things will be identified and someone will inevitably make a new tool that is better than Vite, and I will happily switch to it. Not because I like changing tooling, but because from a practical stand point it will be better, and I will see the value in it and switch. That's it.

Even if you think "nope, there is nothing left to do with our tooling, we've perfected minification". Do you think we have perfected everything on the web? What features of the web exist today that did not 10 years ago? What if, hypothetically, 10 years from now we finally have something in the browser that replaces Web Components and *doesn't suck*? Won't we need some form of new build tooling to transform our code and take advantage of these native features? Just like we have today? As networks and internet protocols change and improve, how we optimize our bundles for them will change too. The web has always changed and evolved. It's never stopped. It will continue to change, and our tooling will continue to react to those changes.

That will also be the case with everything that Bun is abstracting. When does it decide to drop its ESBuild abstraction and switch to whatever that new thing will be? What if it switches too soon, and the community goes with something else, and it needs to switch again? There's only so much you can do to guard against API changes for your end users. If all of Bun's users need to maintain a bunch of ESBuild plugins to work with Bun, and then ESBuild is removed from under the hood and replaced, then those users are stuck on the old Bun version.

What happens when you use Bun to handle your build AND also your core JS runtime AND your testing tools. Then Bun does a major breaking change to one of those systems requiring a lot of tech debt to update your codebase to be able to switch over. Maybe your tests all need upgraded to work with the new system (I've done 3 major test refactors in my work codebase, the longest taking ~6 months to complete, this stuff happens). It could take months, maybe even a full year to upgrade all your code. And in the mean time you're stuck on the old version of Bun until everything works with the new version. BUT OH NO! A big security issue is found in the JS Runtime. So you need to update the JS Runtime, but you can't do that because your JS Runtime and your build tool and your testing tool are all the same. Until your major test refactor is complete, your code is vulnerable. In some industries you are required to address security issues in a certain window of time. Bun is a no-go for those folks.

There are ways for them to deal with this, like shipping multiple build tools, or testing tools, and letting you switch to the new one or old one via a CLI argument. But how long do they support multiple alternative tools being built in? Can they *afford* to support all of them?

With all the various abstractions for tools they have built in to Bun, it is only a matter of time until the glue holding it all together becomes too much to manage. Node, npm, Jest, Vite, etc. These are all large and very complex problem spaces each tool is separately solving. Even Vitest, under the hood is like 80% shared code with Jest, and just trying to handle the other 20% is a major effort.

What happens when JavaScript [Shadow Realms](https://github.com/tc39/proposal-shadowrealm) are released? Vitest is already planning on adopting Shadow Realms as a way to isolate JavaScript tests without having to spin up new Node processes. If my Vitest code is reliant on running in this isolation mode and Bun decides to hijack my imports instead of using the actual Vitest imports suddenly my tests could start randomly failing and there won't be anything I can do about it without removing Bun from the equation until they can update their code under the hood to use Shadow Realms. But what if realms are added into V8, but then Apple drags their feet on adding support into Safari for several years (they do that **a lot**). There's literally nothing Bun could do in that scenario other then make their own internal native implementation of shadow realms until the feature is built in to Webkit. Which would be a pretty major undertaking and not a very scalable solution long term for other similar problems that come up.

All of these reasons and more are why Bun Version Management is so important. And why having so many tools combined into one isn't as nice as it sounds on paper.


* * *


## Part Three - Random thoughts

* If Bun came out in 2012, it would have had Grunt built in.
* If Bun came out in 2014, it would have had Gulp built in.
* If Bun came out in 2016, it would have had Webpack built in.
* If Bun came out in 2018, it would have had Rollup built in.
* If Bun came out in 2020, it would have had ESBuild built in.
* What will happen in 2026?
* Back in 2014 Meteor JS came out and promised to do everything in one frontend/backend framework. It would handle websockets for you, and do reactive updating of the DOM and assume backend success but automatically rollback the UI if the request failed, to make the UI feel real fast and snappy. It let you have multiple people interacting with content on the same page in real time. And all you had to do was use their all-in-one CLI to run your project locally and deploy it to a free online test bed using your own custom project name.
* In 2023 I tried to run my 2014 Meteor project again and the version of the CLI that is compatible with the project doesn't exist any more and the project cannot be ran locally or deployed without completely re-writing the entire project to the latest version of Meteor. All documentation for the 2014 version is just gone.
* I have seen this movie before, and I know how it ends.


* * *


## Part Four - Final thoughts

I've been very hard on Bun in this post, not because it sucks, but because it's *almost* good. And people will be excited to try it out and not realize all the downsides. Again, just like with Yarn, I was pretty hyped for Bun too. But I've since tempered my excitement and looked at it from a practical, and historical, standpoint.

If Bun actually did everything it claimed, then I would 100% be on board. But the non-portable code, the complete lack of Windows support, and some of the shortsighted choices they've made bring me back to reality.

I hope these critiques will lead to improvements in Bun. I hope that this thought process will allow others to look at Bun from a more cautious and thoughtful perspective. I hope these tales of Yarn and Meteor will allow us as a community to learn from our past.


* * *


## Part Five - My predictions for the future

* Most of the projects Bun picked on will get performance improvements over the next year or so and tighten the gap between them and Bun.
* You will start seeing more and more repos that mention Bun in their README's, maybe exclusively.
* All developers that quit their first dev job after 6 months to become a YouTube Coding Influencer will make a "BUN IS THE FUTURE OMG" video with [this thumbnail](https://i.imgur.com/pSJeVMu.jpg). In the hope that it will trick people into watching their 12 part tutorial series on Bun. Like & Subscribe.
* We have not perfected our tools yet. As we continue to evolve and invent newer and better options Bun will struggle to keep up and people will slowly use it less as they get impatient and are willing to just install a dependency if it means a better, more practical solution to their problems than what they had.
* Bun will probably be around for about 5 years. That seems to be the life span for most similar tooling.
* Bun will eventually have really really great Windows support... probably right as people stop using it.
* For some reason Bun never adds in a version manager and instead 4 competing options show up all sucking in different ways.
* The year is 20XX and we have finally converted the last CJS Node Module to ESM. This was only possible after humanity finally gave in and let the AI take over. Was it worth it?
* Joe Biden will get a second term, but like, no one is really happy about it.
* It turns out that Yarn guy really did see Sasquatch. Now I feel bad for making fun of him. Honestly, Harry and the Hendersons may be worth a rewatch.
* Vue is still better than everything else, but people will just use whatever the youtube coders said was the hot new thing because if it wasn't, why would they have made 20 tutorial videos about it?
* They're going to remake Breaking Bad and it won't be very good.
* Someone in Primagen's chat is actually right about something for the first time ever. Did you know he works at Netflix?