Bun v0.5 is packed with new features including npm workspaces
, Bun.dns
, and support for node:readline
. There’s improved compatibility with node:tls
and node:net
so several database drivers now work in Bun for the first time, including Postgres.js, mysql2
, node-redis
, and others. Bun also continues to get faster and more stable — Buffer
instantiation is 10x faster, crypto.createHasher()
is 50x faster, and bun install
got dozens of bugfixes.
# Install Bun
curl https://bun.sh/install | bash
# Upgrade to latest release of Bun
bun upgrade
Workspaces in package.json
Bun now supports workspaces
in package.json
, and it’s fast. Bun installs the Remix monorepo in about 500ms on Linux.
- 28x faster than
npm install
- 12x faster than
yarn install
(v1) - 8x faster than
pnpm install
What are workspaces?
Workspaces make it easy to develop complex software as a monorepo consisting of several independent packages. To try it, specify a list of sub-packages in the workspaces
field of your package.json
; it’s conventional to place these sub-packages in a directory called packages
.
{
"name": "my-project",
"version": "1.0.0",
"workspaces": ["packages/a", "packages/b"]
}
Bun doesn’t support globs for workspace names yet, but this is coming soon!
This has a couple major benefits.
- Code can be split into logical parts. If one package relies on another, you can simply add it as a dependency with
bun add
. If packageb
depends ona
,bun install
will symlink your localpackages/a
directory into thenode_modules
folder ofb
, instead of trying to download it from the npm registry. - Dependencies can be de-duplicated. If
a
andb
share a common dependency, it will be hoisted to the rootnode_modules
directory. This reduces redundant disk usage and minimizes “dependency hell” issues associated with having multiple versions of a package installed simultaneously.
Bun.dns
and node:dns
Bun can now resolve domain names using the built-in Bun.dns
API. At the moment, Bun.dns
exposes a single function: lookup
.
import { dns } from "bun";
const records = await dns.lookup("example.com", { family: 4 });
console.log(records); // [{ address: "93.184.216.34" }]
We’ve also added a minimal implementation of Node.js’ node:dns
that uses Bun.dns
under the hood. It’s powered by c-ares and non-blocking getaddrinfo
on MacOS.
import { resolve4 } from "node:dns/promises";
const records = await resolve4("example.com");
console.log(records); // [ "93.184.216.34" ]
Sockets using node:tls
and node:net
Bun now supports the creation of sockets using net.connect()
and tls.connect()
. This unblocks several database driver libraries. A handful of representative examples:
Connect to Postgres in Bun using Postgres.js by @porsager:
import postgres from "postgres";
const sql = postgres();
const [{ version }] = await sql`SELECT version()`;
console.log(version); // "PostgreSQL 14.2 ..."
Connect to MySQL in Bun using mysql2
client by @sidorares:
import { createConnection } from "mysql2/promise";
const connection = await createConnection({
host: "localhost",
user: "root",
database: "test",
});
const [rows] = await connection.execute("SELECT 1+2 AS count");
console.log(rows); // [{ count: 3 }]
Connect to Redis from Bun using the official Node.js client:
import { createClient } from "redis";
const client = createClient();
await client.connect();
await client.set("key", "Hello!");
const value = await client.get("key");
console.log(value); // "Hello!"
Support for node:readline
Bulding CLI tools should be much easier now that Bun supports the node:readline
module.
import * as readline from "node:readline/promises";
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: true,
});
const answer = await rl.question("How fast is Bun from 1 to 10?n");
if (parseInt(answer) > 10) {
console.log("Good answer!");
}
Running this script yields:
$ bun readline.ts
How fast is Bun from 1 to 10?
> 11
Good answer!
A long-standing feature request on the WebSocket
spec is the ability to set custom headers when opening a WebSocket. While this hasn’t yet landed in the WebSocket standard, Bun now implements it. This allows users to customize the headers used for the WebSocket
client handshake request.
const ws = new WebSocket("ws://localhost/chat", {
headers: {
Authorization: "...",
},
});
Improvements to bun wiptest
While bun wiptest
is still a work in progress, we continue to increase Bun’s compatibility with Jest.
test.skip()
You can use test.skip()
to skip unwanted tests.
import { describe, test, expect } from "bun:test";
describe("fetch()", () => {
test.skip("can connect to localhost", async () => {
const response = await fetch("http://localhost");
expect(response.ok).toBe(true);
});
test("can connect to example.com", async () => {
const response = await fetch("http://example.com");
expect(response.ok).toBe(true);
});
});
When you skip a test, it will appear as grayed out in the test output.
expect(fn).toThrow()
You can use expect(fn).toThrow()
to catch expected errors.
import { test, expect } from "bun:test";
test("catch error", async () => {
expect(() => {
throw new Error();
}).toThrow();
});
describe
labels are included in the output
Previously, nested describe
labels were not included in the test runner output. Thanks to @ethanburrell, this has been fixed.
Before:
After:
✓ outer > inner > my test
Test file:
import { describe, test } from "bun:test";
describe("outer", () => {
describe("inner", () => {
test("my test", () => {});
});
});
Performance boosts
10x faster new Buffer()
Previously, the Buffer
implementation in Bun was using Object.setPrototypeOf()
to create each new instance. Eliminating this bottleneck makes it 10x faster to instantiate a small Buffer
in Bun.
50x faster crypto.createHash()
Previously, Bun was using a pure JavaScript implementation of crypto.createHash()
. Now it’s implemented using native code from BoringSSL, yielding a 50x speed improvement.
Support for HTTPS_PROXY
Bun will now recognize the HTTPS_PROXY
, HTTP_PROXY
, and NO_PROXY
enviroment variables when making outgoing HTTP requests, which includes fetch()
and bun install
. These variables allow you to specify a proxy to forward, or not forward, certain HTTP requests and are useful when running Bun within a corporate firewall.
export HTTPS_PROXY="http://proxy.example.com:8080"
export NO_PROXY="localhost,noproxy.example.com"
If you want to learn more about these variables, GitLab wrote a nice explainer.
Module resolution changes
There are two changes to module resolution that may impact a few packages.
- Bun no longer checks the
browser
property inpackage.json
. This is because some packages would disable Node.js functionality, which is not what we want for Bun. - For better Node.js & npm compatibility, Bun’s JavaScript runtime now reads the
"node"
export condition in package.jsonexports
.
The order Bun’s JavaScript runtime reads package.json "exports"
conditions is:
["bun", "worker", "module", "node", "browser", "default"];
This means that if a package has a "node"
export condition, it will be used instead of the "default"
or "browser"
export condition.
Changelog
While we continue to add new features to Bun, we’re still focused on improving stability and fixing bugs. This release fixes a number of issues
Fixes to bun install
Several bugs with Bun’s package manager are fixed in this release, mostly by @alexlamsl. Thanks Alex!
#1664 |
Previously, scoped and private packages configured with bun install would have a registry of localhost , which made very little sense. We’ve fixed this and private registries will now default to the default registry if not specified, which is usually registry.npmjs.org |
#1667 |
Typically, npm clients are supposed to pass the npm-auth-type header, but bun install wasn’t. We’ve fixed this and now bun install will pass the npm-auth-type header |
a345efd |
In some CI environments, like Vercel, linking node_modules/.bin would fail because the /proc filesystem (used to resolve absolute file paths) wasn’t mounted. We’ve fixed this by falling back to fchdir and getcwd when /proc/fd is not available |
385c81d |
A crash sometimes happened when running bun add if the "dependencies" list went from empty to not empty in a package.json |
#1665 |
Use npm as default registry when scopes are configured |
#1671 |
Fix logging verbosity in bun install |
#1799 |
Fix lifecycle script execution in bun install |
New APIs
Additional fixes
Contributors
Thank you to everyone who contributed to Bun v0.5!
- @Vexu for helping upgrade Bun to the latest version of Zig
- @alexlamsl for
npm
workspaces,net.Socket
, improvements tobun install
, and many many fixed bugs - @ThatOneBro for
node:readline
- @colinhacks for introducing canary builds at
bun-types@canary
- @cirospaciari for implementing
HTTP_PROXY
support - @srh, @lucifer1004, @u9g, @eltociear, @jiaz, @malcolmstill, and @ethanburrell for contributing to Bun
Leave A Comment