Bun is a rival JavaScript runtime to Node.js and Deno. On this article, we take take a look at Bun 1.0, and the explanations it might tempt you away out of your present favourite.
The unique model of this text was printed in early 2023. Now that Bun model 1.0 has arrived, we assessment whether or not this milestone can have any impression on the present JavaScript champions.
The Historical past: The place Bun Matches In with Node and Deno
Ryan Dahl launched Node.js in 2009. It wasn’t the primary server-side JavaScript runtime, however Node.js quickly gained momentum. Model 20 arrived in 2023, and Node.js has the biggest growth ecosystem, with 3.2 million modules — accounting for nearly 500 billion downloads per week (in accordance with npmjs.com).
In 2020, Ryan Dahl launched Deno — a remix of “noDe” — to modernize JavaScript growth and tackle legacy points with Node.js safety, API compatibility, tooling, and module administration. Reception has been constructive, though Deno is but to problem Node’s domination.
In 2022, Jarred Sumner launched Bun following his frustrations with the velocity of Node.js when growing a Subsequent.js mission.
Bun makes use of the JavaScriptCore engine, which powers WebKit browsers similar to Safari, moderately than the V8 engine utilized in Node.js, Deno, and Chrome.
The Bun runtime focuses on efficiency and developer expertise. The purpose is to eradicate slowness and complexity with out throwing away all the things that’s nice about JavaScript.
Bun can evolve quicker than Node.js — which should stay (principally) backward-compatible with the prevailing JavaScript and npm
ecosystem.
Like Deno, Bun has native assist for JavaScript and TypeScript with out requiring a third-party transpiler or configuration.
Bun is turning into a drop-in substitute for Node.js, Deno, serverless runtimes, construct, and testing instruments. It will possibly change npm
, npx
, yarn
, TypeScript compilers, dotenv, nodemon, pm2, Webpack, Babel, and Jest, to supply a whole all-in-one toolbox for growing functions on a single platform.
The unique runtime was steady, however because of contributions from nearly 300 builders, the Bun model 1.0 launch arrived in September 2023. This may inevitably tempt extra builders emigrate to Bun the place they will benefit from the advantages described under.
What’s with the title “Bun”?
The origin of the “Bun” title is unclear, and the brand doesn’t assist! It may relate to the meals, fluffy bunny rabbits, “bundle”, or maybe it’s a brief, memorable title and the bun.sh area was obtainable.
Tasty Bun Advantages
Node.js and Deno use Chrome’s V8 JavaScript engine. Bun opts for the JavaScriptCore engine which powers WebKit browsers similar to Safari. Bun itself is written in Zig — a low-level programming language with guide reminiscence administration and native threading to deal with concurrency. The result’s a light-weight runtime with a smaller reminiscence footprint, faster start-up occasions, and efficiency which may be 4 occasions quicker than Node.js and Deno below sure (benchmarking) situations.
Like Deno, Bun has native assist for each JavaScript and TypeScript with out requiring a third-party transpiler or configuration. It additionally helps .jsx and .tsx information to transform HTML-like markup to native JavaScript. Experimental assist for operating WebAssembly-compiled .wasm information is out there.
Internally, Bun makes use of ES Modules, helps top-level await
, interprets CommonJS, and implements Node’s node_modules
decision algorithm. Bun caches modules in ~/.bun/set up/cache/
and makes use of hardlinks to copy them right into a mission’s node_modules
listing. All initiatives in your system will due to this fact reference a single occasion of the identical library, which reduces diskspace necessities and improves set up efficiency. (Word that macOS installations retain native variations for velocity.)
Bun helps Node’s bundle.json
, npm
equal instructions, and bunx — a npx
-like choice to auto-install and run packages in a single command. For instance:
bunx cowsay "Good day, world!"
bun init
scaffolds empty initiatives in the identical means as npm init
, however you may also template a brand new mission with bun create <template> <vacation spot>
, the place <template>
is an official bundle, a Github repository, or an area bundle. For instance, to create a brand new Subsequent.js mission:
bun create subsequent ./myapp
Bun features a bundler to import all dependencies right into a single file and may goal Bun, Node.js, and client-side JavaScript. This reduces the necessity to use instruments similar to esbuild or Rollup:
bun construct ./index.ts —outdir ./out
Most command-line interface choices can be found by way of a JavaScript API, so it’s potential to create subtle construct scripts and not using a devoted activity runner. Right here’s an equivalent construct to the command above:
await Bun.construct({
entrypoints: ['./index.ts'],
outdir: './out',
})
Bun has a typical check runner like Deno and Node.js 20. Working bun check
executes scripts named like this:
*.check.ts
*_test.ts
*.spec.ts
*_spec.ts
There’s no want for nodemon-like instruments, since bun
has a —watch
flag which restarts scripts or assessments once you modify a dependency file. Restarts are so quick that it turns into potential to live-reload on every keystroke. (Whether or not that is sensible and never a distraction is one other matter!)
Dwell reloading is just not fairly! (Warning: flickering content material!) View authentic animated GIF.
The same —sizzling
mode is out there, the place Bun watches for adjustments and comfortable reloads modules. All information are re-evaluated, however the world state persists.
Atmosphere variables contained in mission .env
information are mechanically loaded and parsed, making them obtainable in Bun functions, so there’s no want to make use of packages similar to dotenv.
In addition to its personal Bun APIs for networking, file entry, little one processes, and so forth, Bun helps:
-
Net APIs similar to
fetch
,URL
,blob
,WebSocket
,JSON
,setTimeout
, and occasions. -
Node.js compatibility APIs similar to
console
,assert
,dns
,http
,path
,stream
, andutil
, in addition to globals together with__dirname
, and__filename
. Bun claims that 90% of the most-used APIs are totally carried out, though it is best to double-check these particular to your mission.
Lastly, Bun has a local SQLite3 consumer — bun:sqlite — which may cut back the variety of dependencies required in some initiatives.
Putting in Bun
Bun is out there as a single binary you’ll be able to set up on Linux, macOS, and Home windows WSL utilizing curl:
curl -fsSL https://bun.sh/set up | bash
It may be put in by way of the Node bundle supervisor:
npm set up -g bun
Or by way of Brew on macOS:
brew faucet oven-sh/bun
brew set up bun
Or by way of Docker:
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun
As soon as put in, you’ll be able to improve Bun utilizing:
bun improve
Or you’ll be able to uninstall Bun by eradicating the ~/.bun
binary and cache listing:
rm -rf ~/.bun
Then replace your shell configuration file (.bashrc
, .zshrc
, or comparable) to take away ~/.bun/bin
references from the $PATH
variable.
Utilizing Bun
Bun is dependable should you use it from the beginning of your mission. Pace is healthier than Node.js, though you’re unlikely to see a big efficiency increase until your app is doing particular intensive duties such heavy SQLite processing or WebSocket messaging.
Node.js compatibility is nice for smaller, less complicated initiatives, and I efficiently launched some scripts utilizing bun begin
with out making adjustments. Extra complicated functions did fail, with obscure error messages generated deep within the node_modules
hierarchy.
Bun vs Deno vs Node.js
Deno addressed lots of Node’s drawbacks, however builders didn’t essentially really feel compelled to modify:
- Deno didn’t assist Node’s third-party modules.
- Migrating from Node.js to Deno required studying new strategies.
- Whereas Deno provided a greater growth expertise, Node.js was ok.
Deno has now added Node.js compatibility choices. That was the simplest approach to get builders to transition to Deno, however within the meantime, Node.js has adopted a few of Deno’s options, together with ES modules, a local check runner, and a —watch
mode.
Bun has taken a special strategy, aiming to be a quick, Node-compatible engine with Deno’s developments. The indicators are promising, however it’s not there but:
- Efficiency is nice, however few builders complain about Node.js velocity.
- Compatibility is nice, however it will likely be a problem to assist all Node.js modules in a special JavaScript engine. Can JavaScriptCore sustain with V8 developments with far much less funding?
- Bun has the potential to interchange your tooling suite, however it’s but to supply the total vary present in Deno.
Compatibility of Bun with Node.js
Node.js compatibility is mostly good for smaller, less complicated initiatives. You might be able to launch some scripts utilizing bun begin
as an alternative of npm begin
with out making any adjustments.
Bun helps:
- built-in Node.js modules and APIs similar to
fs
,path
,http
,console
,assert
, and so forth - world variables and objects similar to
__dirname
andcourse of
- the Node.js module decision algorithm to find information in
node_modules
Bun 1.0 claims to run “nearly any Node.js utility within the wild”. I’m but to be totally satisfied; complicated functions can fail with obscure error messages generated deep inside your third-party modules.
ES Module and CommonJS Compatibility
Bun helps each ESM and CommonJS module methods with top-level await
. ESM took a number of years to reach in Node.js and the ecosystem continues to be dominated by CommonJS. With Bun, there’s no want for particular file extensions (.js
, .cjs
, .mjs
) or "kind": "module"
in bundle.json
. You need to use import
or require()
interchangeably in any file!
Internally, Bun interprets all modules to CommonJS and implements Node’s node_modules
decision algorithm. Whether or not this works as anticipated is one other matter:
- ES6 modules are pre-parsed with a view to resolve additional imports earlier than code is executed. Dynamic imports are potential, however ought to solely be thought-about as a final resort.
- CommonJS modules load dependencies on demand whereas executing the code. Dynamic imports are much less problematic.
Execution order may be important in some functions and it’s the rationale Node.js restricts you to EMS or CommonJS in a single file.
Net APIs
Bun has built-in assist for Net normal APIs obtainable in browsers, similar to fetch
, Request
, Response
, URL
, blob
, WebSocket
, JSON
, setTimeout
, and ReadableStream
. Deno launched these APIs to its server runtime and it makes net coding significantly extra constant. Node.js is catching up however options similar to fetch
arrived not too long ago in model 18.
Bun APIs
Bun ships with highly-optimized normal APIs for frequent operations similar to file studying, file writing, HTTP serving, SQLite querying, and password hashing.
WebSockets are supported alongside HTTP with out requiring a third-party module similar to ws:
Bun.serve({
port: 8000,
fetch(request) {
return new Response('Good day from the Bun server!');
},
websocket: {
open(ws) { ... },
message(ws, knowledge) { ... },
shut(ws, code, purpose) { ... },
}
});
TypeScript and JSX Help
Like Deno, Bun has a JavaScript transpiler constructed into the runtime. You possibly can run JavaScript, TypeScript, JSX, or TSX information with out third-party dependencies. For instance:
bun index.ts
bun index.jsx
bun index.tsx
Bundle Administration
You need to use Bun immediately as an npm
substitute in any Node.js mission. For instance:
bun set up
bun add <bundle> [--dev|--production|--peer]
bun take away <bundle>
bun replace <bundle>
Bun caches modules in ~/.bun/set up/cache/
and makes use of hardlinks to repeat them right into a mission’s node_modules
listing. All initiatives in your system due to this fact reference a single occasion of the identical library. This reduces disk area and improves set up efficiency by as much as an element of 30.
Dwell Reloading
There’s no want for nodemon-like instruments, because the bun
executable has a -watch
flag to restart scripts or assessments once you modify a file.
The same —sizzling
mode is out there, the place Bun watches for adjustments and comfortable reloads modules. All information are re-evaluated, however the world state persists.
Testing
Bun provides a Jest-compatible bun:check
check runner with assist for snapshot testing, mocking, and code protection. For instance:
import { check, anticipate } from "bun:check";
check('2 + 2', () => {
anticipate(2 + 2).toBe(4);
});
Migration from Jest or Vitest is easy, since imports from @jest/globals
or vitest
are internally re-mapped to bun:check
. It shouldn’t be essential to make code adjustments.
Working bun check
executes scripts named:
*.check.ts
*_test.ts
*.spec.ts
*_spec.ts
Script Bundling
Bun is a JavaScript and TypeScript bundler and minifier which may goal code for the browser, Node.js, and different platforms. It’s impressed by esbuild and gives a suitable plugin API:
Bun.construct({
entrypoints: ['index.js'],
outdir: 'construct'
});
Benchmarks illustrate Bun can twice as quick because the Go-compiled esbuild with comparable minification financial savings.
Not like esbuild, Bun doesn’t assist CSS bundling, however that’s more likely to arrive given there’s a common plugin API…
Common Plugin API
Bun’s plugin API is common: it really works for each the bundler and the runtime. You possibly can outline plugins to intercept imports and carry out customized loading logic. This instance implements the import of .yaml
information:
import { plugin } from "bun";
plugin({
title: 'YAML',
async setup(construct) {
const { load } = await import('js-yaml');
const { readFileSync } = await import('fs');
construct.onLoad(yml)$/ , (args) => {
const textual content = readFileSync(args.path, 'utf8');
const exports = load(textual content) as Report<string, any>;
return { exports, loader: 'object' };
});
},
});
Begin-up and Execution Pace
Utilizing bun run <script>
moderately than npm run <script>
usually launches an utility 150ms quicker. That could be a small enchancment, however is’s 4x quicker than Node.js and noticeable once you’re operating many instructions and construct scripts. Efficiency enhancements will likely be larger when utilizing utilizing TypeScript, as a result of there’s no transpilation step.
Bun additionally makes the next Node.js efficiency claims:
- 5x quicker than
npx
- 10x quicker at file reads (utilizing
Bun.learn()
) - 3x quicker at file writes (utilizing
Bun.write()
) - 4x quicker at serving HTTP requests (utilizing
Bun.serve()
) - 4x quicker at SQLite queries (utilizing
bun:sqlite
) - 13x quicker than Jest when testing
- 8x quicker than Vitest when testing
For bundling, Bun is:
- nearly twice as quick as esbuild
- 150x quicker than Parcel 2
- 180x quicker than Rollup with Terser
- 220x quicker than Webpack
You’re unlikely to see such positive factors throughout each mission, however Bun ought to enhance your growth expertise.
Experimental Home windows Version
A local construct of Bun will likely be obtainable for Home windows shortly. It’s extremely experimental and solely helps the JavaScript runtime with out efficiency optimizations. Options such because the bundle supervisor, check runner, and bundler have been disabled till they’re steady.
For the second, Home windows customers can set up Bun on the Home windows Subsystem for Linux — which stays the best choice should you’re doing any heavy JavaScript work.
Abstract: Ought to You Take a Chunk from Bun?
Bun is an completed JavaScript runtime, however Node.js stays the champion for mission-critical initiatives or legacy functions. You must attempt operating your app utilizing bun begin
, however the bigger your codebase, the much less likelihood it is going to execute with out modification.
Deno might be a greater possibility than Bun for brand spanking new initiatives, provided that it’s extra mature and feature-complete.
Bun is nice, and being actively developed, however it’s new. The runtime is steady, however few would guess on its long-term future at this stage. That mentioned, Bun has some fascinating concepts which I hope each the Node.js and Deno groups contemplate adopting (CLI APIs and auto-loaded .env
please!)
On a aspect observe, I like Bun’s title, however it may be tough to seek for assets. ChatGPT makes the daring assertion that “There is no such thing as a extensively identified JavaScript runtime referred to as ‘Bun’. So far as I’m conscious, there is no such thing as a such know-how within the JavaScript ecosystem.” This can be as a result of post-2021 knowledge is proscribed, though sure questions return a Bun response and an apology for the error!
I believe we’re heading towards an age of isomorphic server-side JavaScript, the place module builders try to put in writing code that’s suitable with all runtimes: Node.js, Deno, Bun, serverless, edge, embedded, and so forth. We might ultimately attain a degree the place JavaScript runtimes are principally interchangeable in the identical means browsers are immediately.
The Bun model 1.0 milestone could also be technically meaningless given the minor adjustments from 0.8. The psychological distinction is bigger: Bun feels extra full and usable. Extra builders will contemplate the runtime and toolset for their very own initiatives.
Deno initially went in its personal (good) route however needed to backtrack. It was too radical and too incompatible for a lot of Node.js builders. Switching from Node.js to Deno mid-project nonetheless isn’t one thing it is best to ponder with out accepting the results.
Bun has provided compatibility and velocity from the beginning — a substantial achievement given it’s utilizing a special JavaScript engine. Whether or not it achieves one thing near 100% Node.js compatibility stays to be seen, however you possibly can contemplate it as a drop-in substitute for a few of your toolset on legacy initiatives.
Bun’s velocity claims are spectacular, however few complain about uncooked Node.js efficiency, particularly when it improves with each launch. Some frameworks are gradual, however that’s typically owing to bloat moderately than an inherent fault of the runtime.
For the second, Node.js stays the undisputed JavaScript champion. Few will get fired for selecting Node.js, however Bun has averted a few of Deno’s missteps and is quickly turning into a lovely possibility.