Bun

Bun v0.2.0


Jarred Sumner · October 13, 2022

To upgrade:

bun upgrade

To install:

curl https://bun.sh/install | bash

If you have any problems upgrading

Introducing Bun v0.2.0

https://user-images.githubusercontent.com/709451/195575815-96df744a-1073-4292-b24d-5ba76c20b942.png

New:

  • bun --hot brings hot reloading & zero-downtime restarts to Bun's JavaScript runtime
  • Bun.spawn and Bun.spawnSync (process spawning API)
  • Request.body - incoming HTTP request body streaming with ReadableStream
  • tons of bug fixes & reliability improvements to Bun.serve (HTTP server) and fetch() (HTTP client)
  • Rewrote setTimeout and setInterval for better performance and reliability
  • 2.7x+ lower memory usage for Bun.serve and anything using Response objects
  • "imports" in package.json ("#foo" imports) works now https://github.com/oven-sh/bun/commit/21770eb0f31a43b3d6127ab957e271d029d6bc1b
  • "bun:test" gets ~300x faster when using http server, websockets, etc https://github.com/oven-sh/bun/commit/524e48a81dfc6106ffcdd07b6fd035000b03146c
  • Incrementally write files with Bun.file(path).writer()
  • 30% faster Array.prototype.indexOf for strings (thanks @Constellation)
  • 37% faster Array.prototype.map (thanks @Constellation)
  • 1.4x - 4x faster String.prototype.substring (thanks @Constellation)
  • 2.8x faster String.prototype.replace (thanks @Constellation)
  • new Blob(["hello world"]) is now 75x faster in Bun than Node - https://github.com/oven-sh/bun/commit/2c1926993bc4d94f9e7bc4d171217a707efd385c

Breaking:

  • bun run and bun CLI arguments parsing has been changed so that anything after bun run <file-or-script> or bun <file> is passed through verbatim. This fixes a number of bugs with CLI argument parsing in both bun as a runtime and when used as a package.json "scripts" runner.
# before, server.js wouldn't see the --port argument
bun run server.js --port 3000
  • process.version now reports a fake Node.js version instead of Bun's version. This is for compatibility with many npm packages that check for Node.js version to enable/disable features. To get Bun's version, use Bun.version or process.versions.bun.

  • Bun.serve().hostname should return the hostname instead of the origin. This is a breaking change because it affects how URLs may be printed if you were using this getter before. https://github.com/oven-sh/bun/commit/e15fb6b9b220510df049e782d4f2f6eb3150d069

bun --hot: hot reloads on the server

bun --hot lets you see code changes immediately, without restarting your server. Unlike popular file watchers like nodemon, bun --hot preserves some of the state of your app, meaning in-flight HTTP requests don't get interrupted.

refresh speed comparison
Bun on the left, Nodemon on the right

To use it with Bun's HTTP server (automatic):

// The global object is preserved across code reloads
// You can use it to store state, for now until Bun implements import.meta.hot.
const reloadCount = globalThis.reloadCount || 0;
globalThis.reloadCount = reloadCount + 1;

export default {
  fetch(req: Request) {
    return new Response(`Code reloaded ${reloadCount} times`, {
      headers: { "content-type": "text/plain" },
    });
  },
};

Then, run:

bun --hot server.ts

You can also use bun run:

bun run --hot server.ts

For more information, see bun --hot section in Bun's readme.

Bun.spawn spawn processes in Bun

Bun.spawn efficiently spawns a new process in Bun.

import { spawn } from "bun";

const { stdout } = await spawn(["echo", "hello world"]);
console.log(
  await new Response(
    // stdout is a ReadableStream
    stdout,
  ).text(),
); // "hello world"

Bun.spawn is flexible. stdin can be a Response, Blob, Request, ArrayBuffer, ArrayBufferView, Bun.file, "pipe" or number.

import { spawn } from "bun";

const { stdout } = spawn({
  cmd: ["esbuild"],
  // using fetch()
  stdin: await fetch(
    "https://raw.githubusercontent.com/oven-sh/bun/main/examples/hashing.js",
  ),
});

const text = await new Response(
  // stdout is a ReadableStream here
  stdout,
).text();
console.log(text.slice(0, 128), "..."); // const input = "hel...

stdout and stderr return ReadableStreams when "pipe" is used.

Request.body & Response.body return a ReadableStream

This fixes https://github.com/oven-sh/bun/issues/530

You can read Request & Response objects bodies as a ReadableStream now

ReadableStream now supports async iterators

This works now:

const body = new Response(["hello"]).body;
const chunks = [];
for await (const chunk of body) {
  chunks.push(chunk);
}

Previously, you had to call getReader() like this:

const reader = body.getReader();
const chunks = [];
while (true) {
  const { done, value } = await reader.read();
  if (done) {
    break;
  }
  chunks.push(value);
}

HTTP request body streaming

Bun.serve now supports streaming request bodies. This is useful for large file uploads.

import { serve } from "bun";

serve({
  async fetch(req) {
    // body is a ReadableStream
    const body: ReadableStream = req.body;

    const id = `upload.${Date.now()}.txt`;
    const writer = Bun.file(id).writer();
    for await (const chunk of body) {
      writer.write(chunk);
    }
    const wrote = await writer.close();

    return Response.json({ wrote, id, type: req.headers.get("Content-Type") });
  },
});

"imports" support in package.json

This release adds support for the imports field in package.json

image

Reduced memory usage for Bun.serve()

Bun wasn't correctly reporting memory usage for Request, Response, and Blob objects to JavaScriptCore, causing the garbage collector to be unaware of how much memory was really in use for http responses/requests.

image

bun:test performance improvements

An event loop bug in bun:test caused the process the idle for awhile. Now Bun's own http server tests run > 10x faster.

image

Bug fixes:

  • Fix how console.log handle circular by @zhiyuang in https://github.com/oven-sh/bun/pull/1293
  • Fix nested modules bin executable issue by @zhiyuang in https://github.com/oven-sh/bun/pull/1299
  • Fix install error when node_modules already in npm package by @zhiyuang in https://github.com/oven-sh/bun/pull/1301
  • Fix fetch response redirected by @zhiyuang in https://github.com/oven-sh/bun/pull/1303
  • Fix occasional crash with .json() https://github.com/oven-sh/bun/commit/dfefb05b10e57e01faab0d633fc9538a571a566f
  • Fix incorrect hostname logic in Bun.serve() https://github.com/oven-sh/bun/commit/167948f5c3afc0a4dc482222e42bd255951084ff
  • Allow .env files to define the same key multiple times https://github.com/oven-sh/bun/commit/e94e6d8d95061c8bdb07ce96bc836689f49aafdd
  • Fix crash when creating an empty array https://github.com/oven-sh/bun/commit/16b1e84138056774684b5e769a20dabd787d069c
  • Fix console.log not printing an empty line https://github.com/oven-sh/bun/commit/b733125085a5746af121ce6d7b67eb45fb8e85e3
  • Fix potential crash when TS code has an unexpected ")" https://github.com/oven-sh/bun/commit/a8ab18bd50b3a98c65c6ce96bd75d87d7893df12
  • Support all ArrayBufferView in all hashing functions and node fs functions https://github.com/oven-sh/bun/commit/9d7bcac680c5f32d3fa89d9e47972957279a1a05
  • Fix DotEnv Loader ignoring error log level - https://github.com/oven-sh/bun/commit/906e97223a3dd95801bc0d12f62314719c554fd6
  • Fix missing path/posix and path/win32 https://github.com/oven-sh/bun/commit/dbccfc2b26371c921f3b3a55b03e8bb4a103444f
  • Fix cancel not working in some cases in ReadableStream
  • Fix crash in TextEncoder with rope strings that happens sometimes https://github.com/oven-sh/bun/commit/6b7a0c1d3fde32b6e3ded85456d0721c34aa9219
  • bun:sqlite Fix crash in Database.deserialize https://github.com/oven-sh/bun/commit/9fd00727406b0170fa2d3bb43973ff8d78e7bb76
  • Bun segfalts when tsconfig specifies a jsxFactory #1269
  • unable to use EventEmitter with "require", empty object instead of a class #1284
  • segmentation fault on "napi_wrap" when trying to call a loaded .node extension #1286
  • "assert is not a function" error when calling the assert module as a function #941

More changes:

  • Bun.which(bin): find the path to a command

  • process now extends EventEmitter

  • Minor tweaks to bun:test output. now it includes "expect calls"

    image
  • bun:test print test failures at the bottom - https://github.com/oven-sh/bun/commit/c57b32fa0cdeaf7f1490bd6af9c5248a92c71ea0

  • navigator.userAgent and navigator.hardwareConcurrency are now globals

  • require("tty").isatty works now

  • require("fs").rm works now

  • Implement console.count and console.countReset - https://github.com/oven-sh/bun/commit/4060afb7c70dd3ba037bd23c813c22032e2dabe5

    image

  • Internal data structures for fetch() use 82% less memory (9.8 KB -> 1.8 KB)

  • Bun.version reports Bun's version number

  • Bun.revision reports the git commit SHA used at the time Bun was compiled

All the PRs

  • fix: add destination to ADD command in Dockerfile by @DarthBenro008 in https://github.com/oven-sh/bun/pull/1268
  • test: Promisify basic tests by @albertpurnama in https://github.com/oven-sh/bun/pull/1018
  • Add body to Response and Request by @Jarred-Sumner in https://github.com/oven-sh/bun/pull/1255
  • Fix how console.log handle circular by @zhiyuang in https://github.com/oven-sh/bun/pull/1293
  • docs(thread_pool): comment readability improvements by @ryanrussell in https://github.com/oven-sh/bun/pull/1241
  • Fix nested modules bin executable issue by @zhiyuang in https://github.com/oven-sh/bun/pull/1299
  • Fix install error when node_modules already in npm package by @zhiyuang in https://github.com/oven-sh/bun/pull/1301
  • Fix fetch response redirected by @zhiyuang in https://github.com/oven-sh/bun/pull/1303

New Contributors

  • @DarthBenro008 made their first contribution in https://github.com/oven-sh/bun/pull/1268
  • @albertpurnama made their first contribution in https://github.com/oven-sh/bun/pull/1018
  • @zhiyuang made their first contribution in https://github.com/oven-sh/bun/pull/1293

Full Changelog