Bun is a rival JavaScript runtime to Node.js and Deno. On this article, we take have 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 affect 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. Version 20 arrived in 2023, and Node.js has the biggest improvement ecosystem, with 3.2 million modules β accounting for nearly 500 billion downloads per week (in keeping with npmjs.com).
In 2020, Ryan Dahl launched Deno β a remix of βnoDeβ β to modernize JavaScript improvement and tackle legacy points with Node.js safety, API compatibility, tooling, and module administration. Reception has been optimistic, 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 challenge.
Bun makes use of the JavaScriptCore engine, which powers WebKit browsers reminiscent of Safari, moderately than the V8 engine utilized in Node.js, Deno, and Chrome.
The Bun runtime focuses on efficiency and developer expertise. The intention is to eradicate slowness and complexity with out throwing away every little thing thatβs nice about JavaScript.
Bun can evolve sooner than Node.js β which should stay (principally) backward-compatible with the present JavaScript and npm
ecosystem.
Like Deno, Bun has native help 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 could possibly substitute npm
, npx
, yarn
, TypeScript compilers, dotenv, nodemon, pm2, Webpack, Babel, and Jest, to offer an entire all-in-one toolbox for growing functions on a single platform.
The unique runtime was steady, however due to contributions from almost 300 developers, the Bun version 1.0 release arrived in September 2023. This may inevitably tempt extra builders emigrate to Bun the place they will benefit from the benefits described below.
Whatβs with the identify βBunβ?
The origin of the βBunβ identify 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 identify and the bun.sh area was accessible.
Tasty Bun Advantages
Node.js and Deno use Chromeβs V8 JavaScript engine. Bun opts for the JavaScriptCore engine which powers WebKit browsers reminiscent of Safari. Bun itself is written in Zig β a low-level programming language with handbook 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 sooner than Node.js and Deno underneath sure (benchmarking) circumstances.
Like Deno, Bun has native help for each JavaScript and TypeScript with out requiring a third-party transpiler or configuration. It additionally helps .jsx and .tsx files to transform HTML-like markup to native JavaScript. Experimental help for working WebAssembly-compiled .wasm files is obtainable.
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 challengeβs node_modules
listing. All tasks in your system will subsequently reference a single occasion of the identical library, which reduces diskspace necessities and improves set up efficiency. (Notice 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 "Whats up, world!"
bun init
scaffolds empty tasks in the identical means as npm init
, however you can too template a new project with bun create <template> <vacation spot>
, the place <template>
is an official package, a Github repository, or an area bundle. For instance, to create a brand new Subsequent.js challenge:
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 reminiscent of esbuild or Rollup:
bun construct ./index.ts βoutdir ./out
Most command-line interface choices can be found through a JavaScript API, so itβs doable to create subtle construct scripts with no devoted process runner. Right hereβs an an identical construct to the command above:
await Bun.construct({
entrypoints: ['./index.ts'],
outdir: './out',
})
Bun has a normal test runner like Deno and Node.js 20. Working bun take a look at
executes scripts named like this:
*.take a look at.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 exams while you modify a dependency file. Restarts are so quick that it turns into doable to live-reload on every keystroke. (Whether or not that is sensible and never a distraction is one other matter!)
Reside reloading shouldn’t be fairly! (Warning: flickering content material!) View original animated GIF.
An identical βscorching
mode is obtainable, the place Bun watches for adjustments and smooth reloads modules. All recordsdata are re-evaluated, however the world state persists.
Setting variables contained in challenge .env
recordsdata are routinely loaded and parsed, making them accessible in Bun functions, so thereβs no want to make use of packages reminiscent of dotenv.
In addition to its personal Bun APIs for networking, file entry, little one processes, and so forth, Bun helps:
Web APIs reminiscent of
fetch
,URL
,blob
,WebSocket
,JSON
,setTimeout
, and occasions.Node.js compatibility APIs reminiscent of
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’s best to double-check these particular to your challenge.
Lastly, Bun has a local SQLite3 shopper β bun:sqlite β which may cut back the variety of dependencies required in some tasks.
Putting in Bun
Bun is obtainable as a single binary you’ll be able to set up on Linux, macOS, and Windows WSL utilizing curl:
curl -fsSL https://bun.sh/set up | bash
It may be put in through the Node bundle supervisor:
npm set up -g bun
Or through Brew on macOS:
brew faucet oven-sh/bun
brew set up bun
Or through 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 related) to take away ~/.bun/bin
references from the $PATH
variable.
Utilizing Bun
Bun is dependable if you happen to use it from the beginning of your challenge. Pace is best than Node.js, though youβre unlikely to see a major efficiency enhance until your app is doing particular intensive duties such heavy SQLite processing or WebSocket messaging.
Node.js compatibility is nice for smaller, less complicated tasks, 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 change:
- Deno didnβt help Nodeβs third-party modules.
- Migrating from Node.js to Deno required studying new strategies.
- Whereas Deno supplied a greater improvement expertise, Node.js was ok.
Deno has now added Node.js compatibility options. That was the simplest solution 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 take a look at runner, and a βwatch
mode.
Bun has taken a distinct strategy, aiming to be a quick, Node-compatible engine with Denoβs developments. The indicators are promising, nevertheless itβs not there but:
- Efficiency is nice, however few builders complain about Node.js velocity.
- Compatibility is nice, however will probably be a problem to help all Node.js modules in a distinct JavaScript engine. Can JavaScriptCore sustain with V8 developments with far much less funding?
- Bun has the potential to switch your tooling suite, nevertheless itβs but to supply the total vary present in Deno.
Compatibility of Bun with Node.js
Node.js compatibility is usually good for smaller, less complicated tasks. You might be able to launch some scripts utilizing bun begin
as a substitute of npm begin
with out making any adjustments.
Bun helps:
- built-in Node.js modules and APIs reminiscent of
fs
,path
,http
,console
,assert
, and so forth - world variables and objects reminiscent of
__dirname
andcourse of
- the Node.js module decision algorithm to find recordsdata in
node_modules
Bun 1.0 claims to run βjust about any Node.js software 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 systems 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 "sort": "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 in an effort to resolve additional imports earlier than code is executed. Dynamic imports are doable, 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 essential in some functions and itβs the explanation Node.js restricts you to EMS or CommonJS in a single file.
Internet APIs
Bun has built-in help for Internet commonplace APIs accessible in browsers, reminiscent of 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 reminiscent of fetch
arrived not too long ago in model 18.
Bun APIs
Bun ships with highly-optimized commonplace APIs for frequent operations reminiscent of file reading, file writing, HTTP serving, SQLite querying, and password hashing.
WebSockets are supported alongside HTTP with out requiring a third-party module reminiscent of ws:
Bun.serve({
port: 8000,
fetch(request) {
return new Response('Whats up from the Bun server!');
},
websocket: {
open(ws) { ... },
message(ws, knowledge) { ... },
shut(ws, code, cause) { ... },
}
});
TypeScript and JSX Help
Like Deno, Bun has a JavaScript transpiler constructed into the runtime. You possibly can run JavaScript, TypeScript, JSX, or TSX recordsdata with out third-party dependencies. For instance:
bun index.ts
bun index.jsx
bun index.tsx
Package deal Administration
You need to use Bun immediately as an npm
substitute in any Node.js challenge. 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 challengeβs node_modules
listing. All tasks in your system subsequently 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.
Reside Reloading
Thereβs no want for nodemon-like instruments, because the bun
executable has a -watch
flag to restart scripts or exams while you modify a file.
An identical βscorching
mode is obtainable, the place Bun watches for adjustments and smooth reloads modules. All recordsdata are re-evaluated, however the world state persists.
Testing
Bun provides a Jest-compatible bun:take a look at
take a look at runner with help for snapshot testing, mocking, and code protection. For instance:
import { take a look at, count on } from "bun:take a look at";
take a look at('2 + 2', () => {
count on(2 + 2).toBe(4);
});
Migration from Jest or Vitest is easy, since imports from @jest/globals
or vitest
are internally re-mapped to bun:take a look at
. It shouldnβt be essential to make code adjustments.
Working bun take a look at
executes scripts named:
*.take a look at.jsx
*_test.jsx
*.spec.jsx
*_spec.jsx
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 supplies a appropriate plugin API:
Bun.construct({
entrypoints: ['index.js'],
outdir: 'construct'
});
Benchmarks illustrate Bun can twice as fast as the Go-compiled esbuild with related minification financial savings.
In contrast to esbuild, Bun doesnβt help CSS bundling, however thatβs prone 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
recordsdata:
import { plugin } from "bun";
plugin({
identify: '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 software 150ms sooner. Which may be a small enchancment, however isβs 4x sooner than Node.js and noticeable while youβre working many instructions and construct scripts. Efficiency enhancements will probably be better when utilizing utilizing TypeScript, as a result of thereβs no transpilation step.
Bun additionally makes the next Node.js efficiency claims:
- 5x sooner than
npx
- 10x sooner at file reads (utilizing
Bun.learn()
) - 3x sooner at file writes (utilizing
Bun.write()
) - 4x sooner at serving HTTP requests (utilizing
Bun.serve()
) - 4x sooner at SQLite queries (utilizing
bun:sqlite
) - 13x sooner than Jest when testing
- 8x sooner than Vitest when testing
For bundling, Bun is:
- virtually twice as quick as esbuild
- 150x sooner than Parcel 2
- 180x sooner than Rollup with Terser
- 220x sooner than Webpack
Youβre unlikely to see such good points throughout each challenge, however Bun ought to enhance your improvement expertise.
Experimental Home windows Version
A local construct of Bun will probably be accessible for Home windows shortly. Itβs extremely experimental and solely helps the JavaScript runtime with out efficiency optimizations. Options such because the bundle supervisor, take a look at runner, and bundler have been disabled till theyβre steady.
For the second, Home windows customers can set up Bun on the Windows Subsystem for Linux β which stays the most suitable choice if you happen toβre doing any heavy JavaScript work.
Abstract: Ought to You Take a Chunk from Bun?
Bun is an achieved JavaScript runtime, however Node.js stays the champion for mission-critical tasks or legacy functions. You need to attempt working your app utilizing bun begin
, however the bigger your codebase, the much less likelihood it’ll execute with out modification.
Deno might be a greater possibility than Bun for brand new tasks, provided that itβs extra mature and feature-complete.
Bun is nice, and being actively developed, nevertheless itβs new. The runtime is steady, however few would wager on its long-term future at this stage. That stated, Bun has some fascinating concepts which I hope each the Node.js and Deno groups take into account adopting (CLI APIs and auto-loaded .env
please!)
On a facet be aware, I like Bunβs identify, however it may be tough to seek for assets. ChatGPT makes the daring assertion that βThere isn’t a extensively identified JavaScript runtime known as βBunβ. So far as I’m conscious, there isn’t a such expertise 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 think weβre heading towards an age of isomorphic server-side JavaScript, the place module builders try to write down code thatβs appropriate with all runtimes: Node.js, Deno, Bun, serverless, edge, embedded, and so forth. We might finally attain a degree the place JavaScript runtimes are principally interchangeable in the identical means browsers are right this moment.
The Bun model 1.0 milestone could also be technically meaningless given the minor changes from 0.8. The psychological distinction is bigger: Bun feels extra full and usable. Extra builders will take into account the runtime and toolset for their very own tasks.
Deno initially went in its personal (good) path 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’s best to ponder with out accepting the results.
Bun has supplied compatibility and velocity from the beginning β a substantial achievement given itβs utilizing a distinct JavaScript engine. Whether or not it achieves one thing near 100% Node.js compatibility stays to be seen, however you would take into account it as a drop-in substitute for a few of your toolset on legacy tasks.
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 usually 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 horny possibility.