Technology

Bun: A New JavaScript Runtime that Replaces Node.js

By Naveed SarwarOctober 10th 2023

Bun: A New JavaScript Runtime that Replaces Node.js


Bun: A New JavaScript Runtime that Replaces Node.js

What is a JavaScript runtime?

A JavaScript runtime is a software environment that executes JavaScript code. JavaScript is a programming language that was originally designed for creating dynamic web pages in browsers. However, JavaScript can also be used for other purposes, such as server-side programming, desktop applications, mobile apps, and even games.

To run JavaScript code outside of browsers, you need a JavaScript runtime that can interpret and execute the code. A JavaScript runtime typically consists of two main components: a JavaScript engine and a set of APIs.

  • A JavaScript engine is a program that parses, compiles, and executes JavaScript code. Different JavaScript engines have different performance and features. Some of the most popular JavaScript engines are V8 (used by Chrome and Node.js), SpiderMonkey (used by Firefox), and JavaScriptCore (used by Safari and Bun).

  • A set of APIs are functions and objects that provide access to various features and functionalities of the system, such as file system, network, timers, events, etc. Different JavaScript runtimes have different APIs. For example, browsers have APIs for manipulating the DOM (Document Object Model), making AJAX (Asynchronous JavaScript and XML) requests, using Web Storage, etc. Node.js has APIs for creating servers, working with streams, using buffers, etc.

What is Bun?

Bun is a new JavaScript runtime that claims to be faster, simpler, and more modern than Node.js. Bun was created by Samuel Giddins, a software engineer who works at Apple. Bun was released in February 2023 as an open source project on GitHub.

Bun has several features that make it stand out from other JavaScript runtimes:

  • Bun uses the Zig language to implement its core components. Zig is a fast and safe low-level language that can interoperate with C code. Zig allows Bun to have high performance and low memory usage.

  • Bun uses the JavaScriptCore engine to execute JavaScript code. JavaScriptCore is the same engine used by Safari and other WebKit-based browsers. JavaScriptCore is known for its speed and compliance with the latest ECMAScript standards.

  • Bun provides native implementations of both Node.js and Web APIs. This means that you can use most of the functions and modules that you are familiar with from Node.js or browsers in Bun without any changes. For example, you can use require to load modules, fs to access the file system, fetch to make HTTP requests, WebSocket to create real-time connections, etc.

  • Bun supports TypeScript and JSX out of the box. TypeScript is a superset of JavaScript that adds optional static typing and other features. JSX is a syntax extension that allows you to write HTML-like elements in your JavaScript code. Both TypeScript and JSX are widely used for developing modern web applications. With Bun, you don't need any transpilers or compilers to run TypeScript or JSX files. You can just run them directly with the bun command.

  • Bun has a built-in toolkit for testing, bundling, and scripting. You can use bun test to run your tests with Jest, bun bundle to create a single executable file with your app code and dependencies, and bun script to run any JavaScript file as a script with access to all Bun APIs.

  • Bun has a global cache and workspaces features that make dependency management easier and faster. You can use bun install to install any npm package or GitHub repository in your global cache folder. You can then use bun link to create symlinks from your project folder to the global cache folder. This way, you don't need to install the same packages multiple times for different projects. You can also use bun workspace to create isolated environments for your projects with their own dependencies and settings.

How does Bun compare to Node.js and Deno?

Node.js is the most popular JavaScript runtime for server-side programming. Node.js was created in 2009 by Ryan Dahl, who later regretted some of his design decisions. Node.js uses the V8 engine to execute JavaScript code and provides a set of APIs based on callbacks, streams, buffers, events, etc.

Deno is another JavaScript runtime for server-side programming. Deno was created in 2018 by Ryan Dahl himself as an attempt to fix some of the problems he saw in Node.js. Deno also uses the V8 engine to execute JavaScript code, but provides a different set of APIs based on promises, fetch, URL, etc. Deno also supports TypeScript and WebAssembly natively.

Bun is a new contender in the JavaScript runtime arena. Bun aims to be faster, simpler, and more modern than Node.js and Deno. To see how Bun compares to Node.js and Deno in terms of performance and features, let's look at some benchmarks and examples.

Performance Comparison (numbers from bun's official website)

The results are shown in the table below. The lower the time, the better the performance.

An npm-compatible package manager

A test runner

As you can see, Bun is faster than Node.js and Deno in all tasks.

Why is Bun faster than Node.js and Deno? There are several reasons for that:

  • Bun uses the Zig language to implement its core components. Zig is a low-level language that can produce fast and efficient code that can interact with C code without any overhead.

  • Bun uses the JavaScriptCore engine to execute JavaScript code. JavaScriptCore is a highly optimized engine that can run JavaScript code faster than V8 in some cases.

  • Bun provides native implementations of both Node.js and Web APIs. This means that Bun does not need to use any bindings or wrappers to access the system features, which can introduce some overhead and complexity.

Feature Comparison

To compare the features of Bun, Node.js, and Deno, We used some examples that show how to perform some common tasks, such as TypeScript support, dependency management, bundling, testing, and security. The examples are shown in the code blocks below.

TypeScript Support

TypeScript is a superset of JavaScript that adds optional static typing and other features. TypeScript can help you write more robust and maintainable code by catching errors at compile time.

With Bun, you can run TypeScript files directly without any transpilation or configuration. You just need to use the .ts extension for your files and run them with the bun command.

// hello.ts
function greet(name: string) {
  console.log(`Hello, ${name}!`);
}
greet("Bun");
$ bun hello.ts
Hello, Bun!

With Node.js, you cannot run TypeScript files directly. You need to use a transpiler like tsc or babel to convert your TypeScript files into JavaScript files first. You also need to install some type definitions for Node.js modules from @types and configure a tsconfig.json file for your project.

// hello.ts
import fs from "fs";

function greet(name: string) {
  console.log(`Hello, ${name}!`);
  fs.writeFileSync("greeting.txt", `Hello, ${name}!`);
}

greet("Node");
$ npm install -D typescript @types/node
$ tsc --init
$ tsc hello.ts
$ node hello.js
Hello, Node!

With Deno, you can also run TypeScript files directly without any transpilation or configuration. You just need to use the .ts extension for your files and run them with the deno command.

// hello.ts
import { writeTextFile } from "https://deno.land/std/fs/mod.ts";

function greet(name: string) {
  console.log(`Hello, ${name}!`);
  writeTextFile("greeting.txt", `Hello, ${name}!`);
}

greet("Deno");
$ deno run hello.ts
Hello, Deno!

As you can see, Bun, Node.js, and Deno all support TypeScript natively, but Bun and Deno have an advantage over Node.js in terms of simplicity and convenience. You don't need to install any extra packages or configure any files to use TypeScript with Bun or Deno. You can just write and run your TypeScript code as you would with JavaScript.

Dependency Management

Dependency management is the process of installing and managing the external modules or libraries that your project depends on. Dependencies can help you reuse existing code and add more functionality to your project.

With Bun, you can install any npm package or GitHub repository in your global cache folder with the bun install command. You can then use the bun link command to create symlinks from your project folder to the global cache folder. This way, you don't need to install the same packages multiple times for different projects. You can also use the bun workspace command to create isolated environments for your projects with their own dependencies and settings.

$ bun install express
$ bun install https://github.com/samuelgiddins/bun-example
$ bun link express
$ bun link bun-example
$ bun workspace my-project
$ cd my-project
$ bun link express
$ bun link bun-example

With Node.js, you can install any npm package in your local node_modules folder with the npm install command. You can also use the npm link command to create symlinks from your project folder to another local folder that contains a package. However, you need to install the same packages for each project separately, which can take up a lot of disk space and network bandwidth. You can also use tools like nvm or npmrc to manage different versions of Node.js and npm for different projects.

$ npm install express
$ npm install https://github.com/samuelgiddins/bun-example
$ npm link ../bun-example
$ nvm use 16
$ npmrc -c my-project
$ cd my-project
$ npm install express
$ npm link ../bun-example

With Deno, you can import any module from any URL with the import statement. You don't need to install any packages locally, as Deno will cache them in a hidden folder. However, you need to specify the full URL for each module, which can be verbose and hard to maintain. You can also use tools like deno.land/x or denopkg.com to create aliases for common modules.

import express from "https://deno.land/x/express/mod.ts";
import bunExample from "https://raw.githubusercontent.com/samuelgiddins/bun-example/master/mod.ts";

As you can see, Bun has a simpler and faster way of managing dependencies than Node.js and Deno. You don't need to install the same packages multiple times or specify the full URLs for each module. You can just use the bun install, bun link, and bun workspace commands to manage your dependencies easily and efficiently.

Bundling

Bundling is the process of combining multiple files into a single file that can be executed or distributed. Bundling can help you reduce the number of files and requests, improve performance and compatibility, and obfuscate or minify your code.

With Bun, you can create a single executable file with your app code and dependencies with the bun bundle command. You can also specify some options, such as the output file name, the target platform, and the compression level.

$ bun bundle app.ts --output app --target linux --compress 9

With Node.js, you cannot create a single executable file with your app code and dependencies natively. You need to use third-party tools like pkg, nexe, or webpack to bundle your app.

$ pkg app.js --output app --target linux

With Deno, you can create a single executable file with your app code and dependencies with the deno compile command. You can also specify some options, such as the output file name, the target platform, and the permissions.

$ deno compile app.ts --output app --target x86_64-unknown-linux-gnu --allow-net --allow-read --allow-write

As you can see, Bun and Deno both have a built-in feature to bundle your app into a single executable file. However, Bun has an advantage over Deno in terms of compression. Bun can compress your app file up to 90%, while Deno does not have any compression option.

Testing

Testing is the process of checking if your code works as expected and meets the requirements. Testing can help you find and fix bugs, improve quality and reliability, and prevent regressions.

With Bun, you can run your tests with Jest, a popular testing framework for JavaScript and TypeScript. You can use the bun test command to run your tests with Jest. You can also use the --watch option to run your tests in watch mode, which will rerun your tests whenever you make changes to your code.

$ bun test
$ bun test --watch

With Node.js, you can also run your tests with Jest, or any other testing framework of your choice. You need to install the testing framework as a dev dependency with the npm install command. You can then use the npm test command to run your tests with the testing framework.

$ npm install -D jest
$ npm test
$ npm test -- --watch

With Deno, you can run your tests with the built-in testing API. You can use the Deno.test function to define your tests and the deno test command to run your tests. You can also use the --watch option to run your tests in watch mode.

$ deno test
$ deno test --watch

As you can see, Bun, Node.js, and Deno all have ways of running your tests. However, Bun has an advantage over Node.js and Deno in terms of simplicity and convenience. You don't need to install any testing framework or use any special syntax to write your tests with Bun. You can just use Jest, which is a widely used and well-documented testing framework for JavaScript and TypeScript.

Security

Security is the process of protecting your code and data from unauthorized access or modification. Security can help you prevent attacks, breaches, leaks, and losses.

With Bun, you can control the permissions of your app with the --allow-* options. You can specify which features or resources your app can access, such as network, file system, environment variables, etc. You can also use the --allow-none option to deny all permissions by default and grant them explicitly when needed.

$ bun app.ts --allow-net --allow-read=/tmp
$ bun app.ts --allow-none

With Node.js, you cannot control the permissions of your app natively. You need to use third-party tools like sandbox, vm, or docker to isolate or limit your app's access to the system features or resources.

$ sandbox node app.js
$ node -p 'vm.runInNewContext("app.js", {}, {timeout: 1000})'
$ docker run -v /tmp:/tmp node app.js

With Deno, you can also control the permissions of your app with the --allow-* options. You can specify which features or resources your app can access, such as network, file system, environment variables, etc. You can also use the --prompt option to ask for permissions interactively when needed.

$ deno run app.ts --allow-net --allow-read=/tmp
$ deno run app.ts --prompt

As you can see, Bun and Deno both have a built-in feature to control the permissions of your app. However, Bun has an advantage over Deno in terms of flexibility. Bun allows you to specify different permissions for different files or modules in your app with the --allow-*= options. For example, you can allow network access only for a specific file that makes HTTP requests, while denying it for other files that don't need it.

$ bun app.ts --allow-net=fetch.ts

Conclusion

In this blog post, I have explained what is a JavaScript runtime, why Bun is better than Node.js and Deno, and how you can use Bun to create fast and simple web applications. I have compared Bun, Node.js, and Deno in terms of performance and features using some benchmarks and examples.

Here are some of the main points that I have covered:

  • Bun is a new JavaScript runtime that uses the Zig language, the JavaScriptCore engine, and native implementations of both Node.js and Web APIs.

  • Bun is faster than Node.js and Deno in all tasks measured by the benchmarks.

  • Bun has simpler and faster dependency management than Node.js and Deno with its global cache and workspaces features.

  • Bun has a built-in feature to bundle your app into a single executable file with compression.

  • Bun has a built-in feature to run your tests with Jest without any installation or configuration.

  • Bun has a built-in feature to control the permissions of your app with more flexibility than Deno.

Of course, Bun is not perfect and has some drawbacks as well. Here are some of them:

  • Bun is still in development and may have some bugs or issues.

  • Bun has less community support and documentation than Node.js and Deno.

  • Bun may not be compatible with some Node.js or Web modules that rely on specific features or behaviors of V8 or browsers.

Globe

COPYRIGHT © 2024 TECHLOSET. ALL RIGHTS RESERVED.