Skip to content

Bun v0.2.0

Compare
Choose a tag to compare
@Jarred-Sumner Jarred-Sumner released this 13 Oct 23:48
· 1320 commits to main since this release

To upgrade:

bun upgrade

To install:

curl https://bun.sh/install | bash
If you have any problems upgrading

Run the install script (you can run it multiple times):

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

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 21770eb
  • "bun:test" gets ~300x faster when using http server, websockets, etc 524e48a
  • 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 - 2c19269

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. e15fb6b

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.

Bun v0.2.0 Nodemon

Screen Recording 2022-10-06 at 2 36 06 AM

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

server.ts (vanilla JavaScript works too)

// 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 #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 #1293
  • Fix nested modules bin executable issue by @zhiyuang in #1299
  • Fix install error when node_modules already in npm package by @zhiyuang in #1301
  • Fix fetch response redirected by @zhiyuang in #1303
  • Fix occasional crash with .json() [https://github.com/oven-sh/bun/commit/dfefb05b10e57e01faab0d633fc9538a571a566f]
  • Fix incorrect hostname logic in Bun.serve() 167948f
  • Allow .env files to define the same key multiple times e94e6d8
  • Fix crash when creating an empty array 16b1e84
  • Fix console.log not printing an empty line b733125
  • Fix potential crash when TS code has an unexpected ")" a8ab18b
  • Support all ArrayBufferView in all hashing functions and node fs functions 9d7bcac
  • Fix DotEnv Loader ignoring error log level - 906e972
  • Fix missing path/posix and path/win32 dbccfc2
  • Fix cancel not working in some cases in ReadableStream
  • Fix crash in TextEncoder with rope strings that happens sometimes 6b7a0c1
  • bun:sqlite Fix crash in Database.deserialize
    9fd0072
  • 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 - c57b32f
  • navigator.userAgent and navigator.hardwareConcurrency are now globals
  • require("tty").isatty works now
  • require("fs").rm works now
  • Implement console.count and console.countReset - 4060afb
    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

New Contributors

Full Changelog: bun-v0.1.13...bun-v0.2.0