Trying to subvert the JavaScript ecosystem? After trying out the new JS runtime Bun for myself, I think the future is promising

Author | Forrest Allison

Translation | Nuka-Cola

Finally someone is coming out and going head-to-head with the JavaScript ecosystem. This guy knows what he’s doing, and he also paints a picture of the wonderful new world that will be created after killing JS.

In 2022, former Stripe developer Jared Sumner released Bun, a runtime developed in the Zig programming language. As far as I know, Bun was originally just a JavaScript webserver, but in the subsequent development, the ambition to completely subvert the JS ecosystem has gradually brewed.

According to my personal attention, the advantages of Bun are as follows:

  • Said to provide a faster JavaScript/TypeScript runtime than Node or Deno

  • Package manager is hundreds of millions of times faster than NPM or Yarn

  • Browser Bundler – Full support for tsx, jsx, css, svg and more, can replace everything from webpack to react-scripts and still be lightning fast

  • Provides an extremely fast webserver (replaces Express)

  • Sqlite client

  • Bread

Bun’s idea of ​​changing the dynasty looks very simple and rude – I want to have some JS, and I want to be simpler and more efficient. There is no cleverness here, there is no curve to save the country, what is needed is a head-on confrontation and everything is better than JS. Write extremely fast code in a low-level language, and this is Bun.

Bun is still young and perhaps not ready for those heady real production use cases. But it’s growing fast, so if Bun does gain market share quickly in a few years, I think it makes perfect sense.

1 What’s wrong with the previous plan?

I don’t know if you have written JS or TS production code in actual work, that kind of experience is quite uncomfortable. Open source tools and small projects work well for the most part, but often fall apart when it comes to commercial and enterprise use cases. And because the traditional and conventional route doesn’t work, companies can only try various methods to make the project work normally in the production environment.

For example, TypeScript has solved many long-standing problems in projects involving multiple developers, so as long as the JS road does not work, we can introduce TS for code conversion at any time. I would like to sincerely thank Microsoft here. NPM is too slow for large projects and monolithic repos, so companies may need to turn to Yarn. Here again, thanks to Facebook. All in all, we’re trying our best to piece together things and finally come up with something that’s barely passable.

The author mentioned that it takes 79 seconds to execute eslint on the entire single repo of his enterprise, so it can only be configured separately to ensure that lint is only executed on the files that have changed. Although more complex elements will be introduced, there is no way.

In general, countless developers are speeding up certain parts of the JS toolchain in their own way. Like replacing NPM with Yarn 3’s crazy “plug-and-play” node module virtualization speed, or solving Express’s slow speed with a JSON Schema-based request parser. In fact, most of the original tools have similar problems, and they are written by JS developers for JS developers. Writing in JS is equivalent to being slow…

As a result, some high-speed tools written in faster languages ​​became popular. Every business with a large React application must have experienced a WebPack build that took a full minute. To do this, they had to move to writing esbuild in Go. Likewise, alternatives to eslint in other languages ​​are starting to appear, such as rewriting Rome in Rust.

Bun is a natural continuation of this trend, but takes a bottom-up path of advancement. The core idea of ​​this project is to start from scratch and rewrite the entire JavaScript ecosystem in a low-level language with built-in “batteries”. And so far, the results are really good.

What can 2 Bun do now?

make the interpreter fast

I’d certainly welcome if Bun were just a rewrite of all the JS helpers, but then it’s just another Node.js replacement. Bun isn’t so lazy, it’s trying to make the interpreter itself fast too.

Bun is written in Zig and works with Apple’s JavaScriptCore, similar to how Node uses v8. Zig is an emerging low-level language, mainly active in C++-dominated scenarios. I’m not a low-level developer, so I haven’t used it myself, and I’ll leave more details to other bloggers with stronger skills. In this article, you only need to know that the code written by Zig is fast. As for JavaScriptCore, it does the same thing as v8, only v8 comes from Google and it comes from Apple. JavaScriptCore is used in Safari and many other Apple projects.

The jury is still out on how much faster Bun is than Node, but it is claimed to be significantly faster in certain scenarios. Many friends may not have experienced the era when io.js was just born. In conclusion, a fork that could simply improve the speed of the interpreter was enough to shake the entire JS ecosystem. And Bun’s startup speed is much faster than Node’s. My own personal experiment is about 7 milliseconds, which is about 10 times faster than Node.js, so it is especially suitable for serverless environments and edge computing scenarios.

This wave of subversion relies not only on speed advantages, but also Bun has added many excellent standard library functions. For example, Bun.write() is a new function for writing files that returns a promise, and which it claims can be further sped up with a more suitable system call.

Speaking of Node APIs, Bun currently supports about 90% of the existing Node APIs. Node is very large, and there are always some things that you have never used or heard of (such as new AsyncLocalStorage() ), so it is good to be able to support 90%. Who will run all the packages on NPM? It is not needed at all, and it basically does not affect our daily development.

By the way, TypeScript is quite versatile on the Bun side, just call bun my-ts-file.ts directly. Deno’s support for TS is at this level. Use Bun to template new projects, or add bun-types to tsconfig, and autocompletion in the IDE will work for these new functions!

One of the original goals of the Bun project was to create a faster and more powerful TypeScript compiler. This goal has now been achieved, while being submerged in numerous other features. But at present, it still cannot support some more advanced TypeScript configurations and functions, such as decorators, extension functions that combine multiple configurations in tsconfig, etc.

Alternative to npm

Let’s talk about one of Bun’s most exciting capabilities – an alternative to NPM. It’s really fast, and it’s fast enough to please everyone.

On Linux, bun install can install packages 20 to 100 times faster than npm install. On macOS, it can also reach 4x to 80x.

I’m sure, no cache is faster, cache is faster, in short, it’s faster.

There have been many programs trying to speed up NPM before. For example, the familiar Yarn Plug-n-Play, its idea is to completely abandon the node_modules folder to speed up package installation. Although there is a certain effect, in actual use, the speedup is not that significant, and there are a lot of polyfills and escape-hatches operations to deal with. It can be used, but I really don’t want to use it again, and I don’t plan to recommend it to everyone.

Pnpm is another emerging NPM alternative that implements some smart optimizations while continuing to be written in TypeScript. In pnpm, node_modules are accessed from the global cache via symlinks, and each package can be installed in its own independent time, without waiting for other packages to complete the current operation.

The basic idea of ​​Bun is the same as NPM, but it is faster. It has its own lockfile format, and the node_modules and package.json in it look unchanged. If you are familiar with file system calls, you can combine low-level access and fast language to achieve extremely fast installation results without any fancy tricks.

Right now, Bun doesn’t provide workspace support, so it’s temporarily impossible to interface with large monolithic repos that expect it to rescue (our project also falls into this category). Fortunately, Bun is maintaining a rapid growth rate, and the roadmap just released a few weeks ago also mentioned workspace support.

Note that you can use Bun as a package manager, transpiler, or interpreter without fully turning to Bun. Just select the part we need and discard the rest. I guess the initial popularity of Bun may also follow this path, that is, to be a useful package manager first, and the rest will be discussed later. In this way, the acceptance threshold will become lower.

Contains transpilers, pointing to webpack, esbuild

Bun includes a transpiler for web browsers, which apparently targets webpack and esbuild. By the way, the parser in Bun is a Zig port of the esbuild parser, lighthearted.

Bun already supports a variety of file types, css, svg, tsx, jsx, ts and so on. Advanced options like CSS in JS also seem to work fine on Bun.

Since Bun includes a project scaffolding with several sets of built-in templates, here we can just call: bun create react my-app

After that, I ran bun dev and ran a react app in the browser. I guess react-scripts could be added directly to Bun’s list of replaced tools.

Change the file extension from jsx to tsx, and the program takes effect immediately. Import svg, no problem. Development mode also seems to support HMR, a must-have tool for front-end developers when using webpack.

So, is there anything missing on the transpiler side? There is still a lot missing, after all, the requirements of the production environment are not simple. The first is minimization, which is the feature that actual users most want to see on the subsequent development roadmap. For a large plugin ecosystem, it is also necessary to have packaging tools that can support different file formats. For example, at present, .vue files and .scss have not actually been implemented, especially .scss, which has been used by generations of developers and must be implemented quickly. At the moment I’m not sure how pluggable the Bun bundler is, and the most important thing is to solve the problem directly within the framework, without relying on a lot of external open source packages.

Other features – Web server and sqlite client

Bun also adds a number of traditional framework elements to the standard library. Personally, I’m not very interested in those library-type features, after all, there is already a great wall of functionality in Node for http servers.

Bun’s webserver looks very simple. Express is a bit behind the times, but it’s still good enough for most developers (the dev team just provided support for promises this year). The Bun server seems to trust Cloudflare Worker quite a bit. As long as other issues in the JavaScript ecosystem are resolved one by one, perhaps the Bun development team will turn around and polish the webserver. It should be noted that in some cases, clever use of system calls can double the speed of the Bun webserver, especially during file processing.

As for the new SQLite adapter, I think the previous implementation of sqlite in Node is a bit out of the ordinary mind. Most developers these days will use the legacy sqlite 3 package in conjunction with the sqlite packager for promise support. Bun’s solution looks cleaner, so I’m willing to use it even if there’s no big speed advantage.

3 The fragrance of wine is also afraid of deep alleys

My biggest concern is that so many of the benefits of Bun are difficult to translate into actual appeal to community members. Bun itself is a complete replacement for the JS ecosystem, and it is difficult for ordinary people to accept such a huge change quickly.

Bun is still very young and currently does not have full documentation. For most questions, we can only consult the long readme file. But it’s not difficult to create a docusaurus site and generate corresponding typedoc with TypeScript types with full inline comments, so I guess this should be resolved soon.

4 Comparison of other products

Server-side rendering of React HTTP requests per second (Linux AMD64) comparison, from Bun official website

Deno

If you’ve never heard of Deno and don’t intend to, just skip this chapter. And personally, I think Bun is more up-and-coming than Deno.

Deno, the creator of Node, claims to have solved some of the biggest problems that have plagued developers for a long time. It sets es-modules as default, introduces first-party TypeScript support (no need to transpile NPM modules before publishing), and more. But in my opinion, while Deno solves old problems, it also introduces a lot of new ones.

First, Deno’s changes to package parsing and syntax were too drastic to be compatible with the original NPM ecosystem. In other words, Deno needs to cultivate its own new library ecosystem. Although Deno is slowly starting to support some early libraries, I think the influence of a project will directly determine its development ceiling, so the boundary of Deno is estimated to be here. Of course there are workarounds like converting NPM packages to CDNs of Deno packages, but I don’t think it’s a good idea.

Deno also has quite a few issues that, in my opinion, reveal its semi-finished identity, such as the lack of package.json. Deno does not allow developers to write extensible metadata for their own packages, either from a module resolution perspective or from the lack of a manifest file. GoLang even introduced go.mod specifically for this.

In addition, I think the sandbox/permission system in Deno’s design should be the right idea, but the granularity is not fine enough. It’s at the top level of the whole project, out of the package hierarchy, which means that large applications still need all permissions eventually, so the problem goes back to square one. And as a security company, we were disappointed that Deno was unable to protect large applications from supply chain attacks. Of course, Bun didn’t say how to solve this problem, I’m just venting my dissatisfaction here.

So to sum up: Bun has far more development potential than Deno. The specific reasons are as follows:

  • It supports all the libraries in the existing NPM ecosystem, and supports all the code you have already written, not even the package.json needs to be changed.

  • It addresses several prominent problems in the ecosystem (especially the demands of large enterprises) and integrates the solutions into a single framework.

  • It works in the way people are already familiar, just faster. There is no need to change the paradigm, nor do you force a change in thinking, just use it.

  • You can use it with confidence. Even if we feel that Bun slows down the development speed, we can only use its package manager; or if we think that webpack is too slow, we can only use its packager.

  • It’s faster in almost every dimension, which is a huge advantage. As you can see from io.js, people are willing to switch camps for performance.

Rome

As mentioned above, Rome is a validator. Rome’s maintainers have started rewriting in Rust instead of JS, and the 79-second verification time is a bit exaggerated. (No kidding, our eslint took 79 seconds.)

From the roadmap, Rome also intends to introduce bundlers, documentation generators, compressors, type checkers, testing frameworks, and more. But it’s not all done yet, and Bun has clearly gone further. At least Rome hasn’t started rewriting the Node core itself, so I think that’s about as far as it goes.

In conclusion, many projects have identified existing problems in the Node ecosystem, and each attempted to solve them in one fell swoop within a unified high-performance framework. Next, see who develops faster.

5 Ecological camps in the open source world

Here I would like to narrow down the field of vision and talk about how the ecological camp in the open source world came into being through specific cases.

I believe that many Node developers know how Jest has overwhelmed the Mocha testing framework and has risen rapidly all the way. Mocha was also the preferred test runner back in the day, with good results and good syntax, but when more complex requirements or assertions were involved, additional modules and plugins had to be introduced. Fortunately, with community collaboration, plugins are not too difficult to find. In summary, developers need to have a broader knowledge to import the corresponding library.

Later, Facebook came up with Jest, a test framework containing “batteries”. It borrows Mocha syntax and libraries and consolidates everything into a single framework. Jest can solve everything from fake timing to requirement detection and simulation. Jest also has room for expansion, but I’ve only used it once in real work. Most of the proof-of-concept and design was undertaken by Mocha, with Jest as a latecomer just unifying the work and making it more accessible. While Mocha also has die-hard fans, Jest is definitely more popular.

There are many such cases in the open source world. The first solution has the first-mover advantage, and once the growth is weak in the future, there will be enthusiastic developers to integrate the functions. This also reminds me of systemd when the Linux family was not unified. Today, systemd manages almost everything on most Linux distributions, and Bun may take the JavaScript world by storm in the same way.

I realize that from an open source perspective, this kind of merging and unification seems to be against the spirit of open source, but implementing simple requirements with a large number of libraries has indeed become a pain point tormenting developers. And if each library has a corresponding maintenance team, a malicious hacker can carry out a supply chain attack by simply forging an email domain. We don’t want that, but the reality is so cruel. It is easy to be recruited by veterans, let alone newcomers who have just been exposed to a lot of names and are not yet familiar with various languages. So from a pragmatic point of view, I think many of my friends should be like me, and I don’t think that introducing more common functions into the standard library and integrating multiple development tools into a unified framework is a historical regression.

6 Conclusion

As of July 2022, Bun is still not ready for production, but I strongly recommend that you try it yourself. The whole process is very convenient, and I think Bun is more than enough for small sub-projects or simple internal dashboards in a company now.

I can’t say whether or even how Bun will reshape the face of JavaScript in the next few years, but I’m really looking forward to its evolution.

The text and pictures in this article are from InfoQ

loading.gif

This article is reprinted from https://www.techug.com/post/trying-to-subvert-the-javascript-ecosystem-after-personally-trying-out-the-new-js-runtime-d87073aa4a7d8fa024c9/
This site is for inclusion only, and the copyright belongs to the original author.

Leave a Comment