Unleashing the Speed: Exploring the Power of Bun.js and the Future of JavaScript Runtimes
It’s no secret that JavaScript developers love to reinvent the wheel. We spend countless hours building libraries and frameworks for tasks that have already been solved by existing solutions. But it seems that some developers have taken this trend to the next level and have decided to reinvent the entire runtime itself.
Bun.js, is a new and ambitious JavaScript toolset and runtime that has been making waves in the tech world. It promises to be incredibly fast and is being touted by some as a Node.js killer. In this article, we will explore what Bun is, how it works, and whether it really is as fast as people claim. We’ll also compare it with Node.js and see if it can truly replace it as the go-to JavaScript runtime. Let’s dive in!
average javascript enjoyer:
Introduction: The Basics
Development of JavaScript Frameworks Over Time
JavaScript was invented by Brendan Eich in 1995 for Netscape 2, and it became the ECMA-262 standard in 1997. With the emergence of Web 2.0 applications such as Gmail, JavaScript became a more serious language. Over time, JS engines in major browsers started providing better support and performance.
Some notable advancements in the evolution of JS and its tools include:
The release of Node.js in 2009, which uses the V8 engine (Chrome V8), considered one of the best JS engines to date.
The introduction of Webpack in 2012 to solve bundling issues for large projects.
The emergence of polyfills and the introduction of Babel in 2014 to solve browser compatibility issues. Polyfills are now obsolete in 2023.
The original presentation:
JavaScript Runtimes: Understanding Runtimes and their Basics
Before we dive deeper into JavaScript runtimes, let’s first understand what a runtime is. In programming, a runtime is an environment where the code runs and is executed. It includes everything that is needed to execute the code, such as libraries, frameworks, and tools.
A JavaScript runtime specifically is an environment where JavaScript code is executed. There are various JavaScript runtimes available in the market today. The most popular one being Node.js, which we will discuss in more detail later.
Let’s take an example:
JavaScript code is like fuel, which is used to power the car. Just like fuel, JavaScript code is inert and cannot do anything on its own. It needs something to process and execute it.
That’s where the runtime environment comes in, which is like the engine of the car. The runtime environment takes the JavaScript code, processes it, and generates machine code that can be executed by the computer.
Here are a few things to keep in mind:
The engine (runtime) is responsible for the conversion of fuel (JavaScript code) into raw energy (machine code).
The engine (runtime) is not the only component required to make the car (Node.js) work. It needs other components (Node APIs) to perform various tasks.
The engine (runtime) can vary in its quality and efficiency, just like different car engines can have different power and fuel efficiency.
To summarize, it’s something like this:
JavaScript code (fuel) -> Runtime environment (engine) -> Node.js APIs (car)
What exactly is Node.js then?
Overall, JavaScript code alone is not enough to build a functional application. It needs to be processed by a runtime environment like Node.js to generate machine code that can be executed by the computer.
Node.js is a popular JavaScript runtime built on Chrome’s V8 engine. It provides a rich set of APIs that allow developers to build server-side applications using JavaScript. Some popular Node APIs include:
HTTP: Allows building web servers and clients.
File System: Provides APIs for interacting with the file system.
Process: Provides APIs for interacting with the current Node process.
In summary, a JavaScript runtime is an environment where JavaScript code is executed, and Node.js is one of the most popular JavaScript runtimes available today, providing a rich set of APIs for building server-side applications.
Node.js Architecture From A to Z. Use Cases, Advantages, Big Players | LITSLINK Blog
What sets Deno apart from Node.js? A brief introduction to Deno.
Deno is a JavaScript runtime environment that is built on top of V8, the same JavaScript engine that powers Google Chrome. Deno is designed to be a more secure and modern alternative to Node.js.
Ryan Dahl, the creator of Node.js, has expressed regret about some of the design decisions he made when creating Node.js. In a 2018 talk at JSConf EU, he apologized for making Node.js too complex and difficult to use, and for not making it more secure.
Dahl also said that he believes Deno is a better JavaScript runtime than Node.js. Deno is a newer project that is still under development, but it has a number of features that Dahl believes make it superior to Node.js.
Here are some of the key new additions and improvements to Deno:
Running JavaScript code in a secure sandbox by default
Using URLs to import modules from any location
Supporting TypeScript out of the box without any configuration or extra tools
Using ECMAScript modules as the default module system
Providing a standard library with common utilities and Web APIs
Offering a built-in bundler, test runner, formatter, and debugger
So what exactly is this ‘Bun’ we keep hearing about?
Bun is the new kid on the block. It’s a JavaScript runtime that’s a direct competitor to Node and is still in development, but it’s already managed to raise $7 million in funding!
What makes Bun stand out from the crowd is its three major goals:
To execute JavaScript at a BLAZINGLY FAST SPEED 🚀
To provide complete and lightning-fast tooling, including a bundler and package manager
Be a drop-in replacement for all existing Node projects
So how does Bun plan to achieve these goals even though it’s still in the Oven?
Speed: Bun is built on top of the JavaScriptCore engine, which is the same engine that powers Safari and iOS. This gives Bun a significant performance advantage over other JavaScript runtimes, such as Node.js and Deno.
Tooling: Bun comes with a built-in bundler, transpiler, and task runner. This means that you can use Bun to build, test, and deploy your JavaScript projects without having to install any additional tools.
Compatibility: Bun is designed to be a drop-in replacement for Node.js. This means that you can use Bun to run existing Node.js projects without having to make any changes to your code.
Bun is still in development, but it’s already shaping up to be a powerful new JavaScript runtime.
Here are some of the key features of Bun:
Speed: Bun is significantly faster than Node.js and Deno, especially for large applications.
Memory usage: Bun uses significantly less memory than Node.js and Deno, even for large applications.
Ease of use: Bun is very easy to use, even for beginners. It has a simple API that is similar to Node.js.
Documentation: Bun is very well-documented, so it is easy to find help if you need it.
How exactly does JavaScriptCore fit into Bun?
JavaScriptCore is a JavaScript engine that is used by Safari, Apple’s web browser.
Bun uses JavaScriptCore (JSC) as its JavaScript engine, while Chromium uses V8, Firefox uses SpiderMonkey, and Microsoft used Chakra for Internet Explorer but now uses V8 for Edge while Hermes is used for React Native.
JSC is generally faster than V8, especially for large applications. This is because JSC is written in C++, while V8 is written in JavaScript. C++ is a compiled language, which means that it is converted to machine code before it is executed. This makes C++ code faster than JavaScript code, which is interpreted at runtime.
Bun is built on top of JavaScriptCore, which gives it a number of advantages over other JavaScript runtimes, such as Node.js and Deno.
Here are some of the benefits of using JavaScriptCore in Bun:
JIT compilation: Just-In-Time (JIT) compilation is a technique that compiles JavaScript code to machine code at runtime. This makes the code run faster, especially for code that is executed frequently.
Function inlining: Function inlining is a technique that replaces function calls with the actual code of the function. This makes the code run faster, because there is no overhead of calling a function.
Dead code elimination: Dead code elimination is a technique that removes code that is never executed. This makes the code smaller and faster.
Portability: JavaScriptCore is a cross-platform engine, which means that Bun can be used on a variety of operating systems.
Overall, JavaScriptCore is a great choice for a JavaScript engine, and it is one of the reasons why Bun is such a fast and efficient runtime.
Unpacking the Main Selling Point: Performance
How blazingly-fast is bun?
Bun is all about speed, and it’s a key selling point. Built by Jarred Sumner, a former frontend engineer at Stripe, Bun is designed to run most of the world’s JavaScript outside of browsers, bringing performance and complexity enhancements to your infrastructure, as well as better developer productivity through simpler tooling. According to Sumner, Bun processes about three times more HTTP requests per second than Node.js when rendering React server-side.
It’s also equipped with WebSocket, ReadableStream, and fetch, and it’s a transpiler, so TypeScript and JSX work out of the box.
Sumner was frustrated by how slow everything was in JavaScript, and he wanted to make it faster. He explored a number of languages to build Bun but ultimately landed on the relatively little-known Zig, which helped him achieve Bun’s impressive speed. Bun also implements Node.js’ module resolution algorithm, which means that npm packages also work with it.
Jarred Sumner took to Twitter to share some statistics demonstrating how Bun accelerates existing Node APIs such as websockets, readable streams, file read and write, SQLite, and other features. He then compares the performance of these features with other similar tools:
Bun can install npm packages for a simple Next.js app approximately 20 times faster than Yarn and 49 times faster than npm install.
Bun’s implementation of the WebSocket client achieves higher throughput than both the ‘ws’ npm package and Deno’s WebSocket client
Bun is equipped with a high-performance SQLite client
Additionally, Bun has official benchmarks that demonstrate its impressive performance:
Bun’s official benchmarks in https://bun.sh
To sum up, the numbers speak for themselves and Bun is a lightning-fast tool designed to run JavaScript outside of browsers, and it outperforms many other popular tools when it comes to speed and performance.
How is Bun fast?
Bun’s speed is a key selling point of the runtime, and it’s no coincidence that it was designed to beat a slow iteration cycle. Founder Jarred Sumner was frustrated with the speed of the iteration cycle in Next.js while developing a game, leading him to experiment with different builders and transpilers. However, in the end, he developed a runtime that included both, providing faster iteration times.
ziglang/logo: The official Zig programming language logo
One of the unique features of Bun is its use of Zig’s “comptime” metaprogramming approach, which allows arbitrary code to be run at compile time. This approach helped Sumner write fast code, and it is an essential factor in Bun’s high performance and some others include:
- Use of Zig: As the creators of Bun state, one of the reasons for its speed is that its core functionality is written in Zig. The choice to use Zig was based on its low-level control over memory and lack of hidden control flow, which make it much simpler to write fast software. By compiling to machine code, Zig allows Bun to execute code more quickly and with fewer resources than Node.js.
Home ⚡ Zig Programming Language
*Zig is a general-purpose programming language and toolchain for maintaining robust, optimal and reusable software…*ziglang.org
Comptime metaprogramming: Comptime is a metaprogramming approach that allows Bun to run code at compile time. This helps to speed up parsing and other tasks, resulting in faster performance overall.
Bun uses comptime in the lexical analyzer, called the “lexer.” The lexer is responsible for iterating through all of the text to determine if the current token is a valid identifier or a keyword. Because of comptime, Bun uses a bit-set that’s generated at compile time, resulting in a 2% performance boost.
In contrast, Node.js is built on top of JavaScript, which can lead to slower performance. While Node.js does use C++ for some APIs, a lot of the code is in JavaScript. This can result in performance issues when adding additional JavaScript on top of an already JavaScript-heavy codebase. Bun’s use of Zig/C++ for its lowest levels means that when using JavaScript in Bun, you’re actually using purely Zig/C++ underneath, resulting in super-fast performance.
In summary, while both Node.js and Bun are useful tools, their approaches to performance differ. Node.js prioritizes ease of use and flexibility, while Bun is designed for speed and performance.
What else does Bun offer?
Bun is an all-in-one runtime that includes everything you need, unlike Node, which requires additional tools like Webpack, Babel, Jest, and others. Bun also offers a cohesive and modern developer experience, with features such as:
TypeScript and JSX support out of the box: You don’t need to install or configure any extra tools to use TypeScript and JSX in your bun.js projects.
Built-in bundler, transpiler, test runner, and package manager: You don’t need to use external tools like webpack, Babel, Jest, or npm to bundle, transpile, test, and install your JavaScript modules. Bun comes with everything you need to build JavaScript apps. Bun also supports .wasm files for WebAssembly.
Node.js and Web APIs compatibility: You can use hundreds of Node.js and Web APIs in your bun.js projects, such as fs, path, Buffer, fetch, WebSocket, ReadableStream, and more. Bun also supports most native Node modules thanks to its implementation of Node-API functions.
Custom modules for additional functionality and performance: You can use some built-in modules that bun.js provides to access features that are not available in Node.js or Web APIs, such as bun:sqlite for a fast SQLite client, or bun:ffi for a low-overhead foreign function interface.
Compatibility with npm packages and modules: Bun can find and load modules from the node_modules directory using Node’s resolution algorithm.
Support for both ESM and CommonJS modules: Bun can import and export modules using either syntax, but internally it uses ESM for better performance and compatibility.
Automatic loading of environment variables from .env files: Bun can read and use values from .env files to configure your application or pass information to your code.
Bun aims to be a fast, modern, and versatile JavaScript runtime that can run your code anywhere: local, server, or edge. It offers performance and simplicity benefits for your infrastructure, as well as productivity and happiness benefits for your development workflow.
Popular projects supporting Bun
Introducing HonoJS: A Blazingly-fast 🚀 Competitor to ExpressJS
HonoJS is a framework for building web applications and services with JavaScript. It is built on top of the Deno runtime environment, and it provides a number of features that make it easy to build scalable and efficient web applications.
One of the benefits of HonoJS is that it is very easy to use. The framework provides a number of pre-built components that can be used to quickly and easily build web applications. For example, the framework provides a pre-built router that can be used to handle HTTP requests, and a pre-built template engine that can be used to render HTML templates.
Another benefit of HonoJS is that it is very secure. The framework is designed to be secure by default, and it provides a number of features that can help to protect your web applications from attacks. For example, the framework provides a pre-built authentication system that can be used to authenticate users, and it provides a pre-built authorization system that can be used to control what users can do with your web applications.
Finally, HonoJS is very scalable. The framework is designed to be able to handle large volumes of traffic, and it provides a number of features that can help to improve the performance of your web applications. For example, the framework provides a pre-built caching system that can be used to cache frequently accessed data, and it provides a pre-built load balancer that can be used to distribute traffic across multiple servers.
Here are some of the benefits of HonoJS over Express:
HonoJS is built on top of the Deno runtime environment, which is a newer and more modern runtime than Node.js.
HonoJS is designed to be more secure than Express. It does not have access to the filesystem by default, and it only downloads modules from trusted sources.
HonoJS is designed to be more efficient than Express. It uses less memory and CPU resources, which can lead to better performance.
HonoJS is designed to be more scalable than Express. It can handle more traffic and more users, which can make it a better choice for high-traffic applications.
Bun is a supported runtime environment for HonoJS. This means that HonoJS can be used to build web applications and services on Bun.
Introducing Elysia: A Blazingly-fast 🚀 Competitor to Hono 😉
Elysia.js is a web framework built on top of the Bun runtime environment. It is designed to be fast, efficient, and easy to use. Elysia.js is a good choice for developers who want to build web applications that are scalable and secure.
Elysia’s benchmarks
Here are some of the features of Elysia.js:
Fully type-safe web framework: Elysia automatically infers the types from your code and validates the incoming requests to ensure type safety. You don’t need to write types or understand TypeScript to use Elysia.
Optimized for Bun: Elysia leverages the speed and versatility of Bun, which uses JavaScriptCore as its core engine and can run on any platform that supports the Web Standard API.
Familiar syntax like Express: Elysia has a simple and expressive syntax that resembles Express, one of the most popular web frameworks for Node.js. You can easily create routes, middleware, and controllers with Elysia.
End-to-end type safety with Eden: Elysia integrates with Eden, a tool that allows you to create a fully type-safe client for consuming Elysia APIs. Eden creates a single source of truth for your data structure and eliminates any possible type conflict between TypeScript, actual requests, API documentation, and frontend client.
Documentation in one line with Swagger: Elysia supports Swagger plugins that can generate API documentation in just one line of code. You don’t need to write any extra comments or annotations to document your APIs with Elysia.
Elysia - Fast, and friendly Bun web frameworks
Trying out Elysia:
GitHub - vaishnav-mk/elysia-demo
The Backend with Elysia
In this demo project, we have the backend implementation for a contact management app. The backend code is organized into two files: db.ts
and index.ts
.
In db.ts
, we define the ContactDB
class which handles the database operations for contacts. It utilizes the bun:sqlite
package for efficient SQLite database management. The class provides methods for creating, updating, deleting, and retrieving contacts from the database. It also supports searching for contacts based on a query string.
In index.ts
, we set up the backend server using the Elysia framework. We leverage the power of Elysia's middleware ecosystem, including @elysiajs/cors
for enabling CORS support and @elysiajs/swagger
for generating API documentation. The server is configured to listen on port 3000.
The Elysia framework brings several benefits to the table. It emphasizes efficiency and speed, thanks to its optimized design and use of advanced technologies. Compared to traditional frameworks like Express, Elysia outperforms in terms of handling requests and processing data, leading to better overall performance.
This demo project showcases the efficiency and speed of Elysia as a backend framework. By utilizing the ContactDB class and the Elysia framework, we can efficiently manage contacts, perform CRUD operations, and provide a robust API for the contact management app.
In summary, Elysia’s backend implementation for the contact management app offers superior efficiency and speed compared to traditional frameworks like Express. Its optimized design, advanced features, and seamless integration with the ContactDB class make it a powerful choice for building efficient and performant backend applications.
The Frontend with SvelteKit and Tailwind
The frontend of this demo project is a sleek and intuitive contact management app built using SvelteKit and Tailwind CSS. It seamlessly interacts with the backend to provide a smooth user experience.
SvelteKit, a modern frontend framework, is employed to develop the frontend. It leverages the concept of reactive programming, enabling efficient updates and rendering of the user interface. With SvelteKit, the contact management app benefits from faster loading times and reduced bundle size, resulting in improved performance.
Tailwind CSS, a highly customizable CSS framework, is utilized for styling the frontend. It offers a utility-first approach, allowing for rapid development and easy customization. By leveraging Tailwind CSS, the contact management app achieves a visually appealing and responsive design.
The frontend interacts with the backend through well-defined API endpoints provided by the Elysia backend. It utilizes HTTP requests to perform actions such as creating, updating, and deleting contacts, as well as retrieving contact information. These interactions are seamlessly integrated into the user interface, providing a smooth and intuitive user experience.
Overall, the frontend of this demo project showcases the power and versatility of SvelteKit and Tailwind CSS. The combination of these technologies, along with the efficient backend implementation, results in a highly performant and user-friendly contact management app.
If you are interested in reading more about my take on SvelteKit, give this a read:
What the future of Bun holds
Bun.js has ignited a tidal wave of excitement in the JavaScript community. While still in its early stages and not yet production-ready, this revolutionary tool is captivating developers with its blazing-fast speed 🚀, robust tooling, and relentless focus on web development.
With a growing Discord community of over 16k members, the enthusiasm for Bun.js is palpable. It has quickly become a rallying point for JavaScript enthusiasts who eagerly anticipate its full potential. As Bun.js evolves and matures, it is poised to challenge established players and push the boundaries of what is possible in web application development.
This emerging powerhouse serves as a powerful motivator for existing players like Node.js and Deno to elevate their performance and stay competitive. The vibrant ecosystem surrounding Bun.js fosters a spirit of innovation and collaboration, inspiring developers to push the boundaries of what can be achieved.
The future of Bun.js holds great promise. As it continues to evolve, it will empower JavaScript developers and reshape the web development landscape. Together, we are charting a new course towards a more efficient, productive, and exhilarating era of JavaScript development. Join the Bun.js community and be part of this exciting journey towards the future of web development.
Currently, Bun may not be fully compatible with Windows. If you’re using Windows, no worries! You can still enjoy Bun’s powerful features by using Windows Subsystem for Linux (WSL) or exploring the option of dual-booting a Linux distribution like Arch. To keep track of when Bun becomes compatible with Windows and other beloved frameworks, feel free to visit the delightful website https://is-bun-ready.pages.dev/. Happy coding!