Skip to content

Releases: oven-sh/bun

bun v0.0.68

23 Jan 07:30
Compare
Choose a tag to compare

To upgrade:

bun upgrade

bun v0.0.68

This release is mostly focused on bun.js, bun's JavaScript runtime environment. Fixes to bun install will be part of the next release, but the infrastructure work from this release will help with bun install in the next release.

TLDR:

  • Bun.Transpiler lets you run Bun's JS/TSX transpiler programmatically from bun.js
  • bun.js natively implements Node.js' fs module (sync functions), and its fast
  • bun.js has more support for the Node.js process object

Bun.Transpiler - API access to Bun

const bun = new Bun.Transpiler({
  loader: "tsx", // set default loader
});

// logs transpiled code without resolving imports
console.log(bun.transformSync("export default <div />"));

// return list of imports & exports without resolving imports or printing code
const { imports, exports } = bun.scan(`
  import { Component } from "react";
  export const foo: boolean = true;
`);

console.log({ exports, imports });

Bun.Transpiler exposes part of Bun's JavaScript & TypeScript transpiler from native code to JavaScript, and it's fast.

End-to-end, transpiling this JSX file inside JavaScript via Bun.Transpiler runs:

  • 8x faster than swc
  • 15x faster than esbuild
  • 40x faster than babel

image

See benchmark code

Bun.Transpiler supports JavaScript plugins with AST access via macros. Macros are not entirely done yet, but simple ones work. There will be docs on this.

Bun.Transpiler is builtin to bun.js, there's nothing extra to import or install. Eventually there will be a WASM build for some of this, but not sure when

However, a transpiler API is not very useful without a way to read/write files to disk.

Node.js fs module implementation

// This works in bun.js now
import {readFileSync} from 'fs';

// require("fs") also works in both .mjs files and .js/.cjs files
require("fs").writeFileSync("foo.txt", "bar!")

// you can also use the node: namespace if you want
import {readlinkSync} from 'node:fs';

You can now use most of the sync functions from Node.js' fs module inside bun.js. These are implemented from scratch in Zig & exposed to JS. Buffer & streams are not implemented yet, but you can pass a Uint8Array or ArrayBuffer where Node accepts a Buffer. The async versions of the functions will come in a future release (this already was a lot of stuff for one release), but generally sync outperforms async for local file access.

fs.realpathSync is about 7x faster in bun.js (50,000 iterations)

image

fs.existsSync runs about 30% faster in bun.js (100,000 iterations)

image

The following functions are implemented:

  • fs.accessSync
  • fs.appendFileSync
  • fs.chmodSync
  • fs.chownSync
  • fs.closeSync
  • fs.copyFileSync
  • fs.existsSync
  • fs.fchmodSync
  • fs.fchownSync
  • fs.fstatSync
  • fs.fsyncSync
  • fs.ftruncateSync
  • fs.futimesSync
  • fs.lchmodSync
  • fs.lchownSync
  • fs.linkSync
  • fs.lstatSync
  • fs.lutimesSync
  • fs.mkdirSync
  • fs.openSync
  • fs.readdirSync
  • fs.readFileSync
  • fs.readlinkSync
  • fs.readSync
  • fs.realpathSync
  • fs.renameSync
  • fs.statSync
  • fs.symlinkSync
  • fs.truncateSync
  • fs.unlinkSync
  • fs.utimesSync
  • fs.writeFileSync
  • fs.writeSync

Bun also includes an implementation of Node's SystemError with pretty printing. Note that since source maps are not implemented yet, sometimes the line:column will be off by a little.

image

This is what the same error looks like in Node

image

Node.js process object

bun.js has more support for the process object from Node.js.

// These work now in bun.js
process.chdir("insert-dir-name-here");
process.cwd();
// arguments used to launch, excluding "run" if via "bun run" for compatibility with npm packages
process.argv;
// current process id
process.pid;
// parent process pid
process.ppid;

// returns bun's version
process.version

process.versions
{
  // fake version for compatibility with npm packages potentially looking this up
  "node": "17.0.0",
  "modules": "67",
  // bun version
  "bun": "0.0.68",
  // git shas/tag of bun dependencies
  "webkit": "96e77eccfde8dc9c207520d8ced856d8bdb8d386",
  "mimalloc": "f412df7a2b64421e1f1d61fde6055a6ea288e8f5",
  "libarchive": "dc321febde83dd0f31158e1be61a7aedda65e7a2",
  "picohttpparser": "066d2b1e9ab820703db0837a7255d92d30f0c9f5",
  "boringssl": "b3ed071ecc4efb77afd0a025ea1078da19578bfd",
  "zlib": "959b4ea305821e753385e873ec4edfaa9a5d49b7",
  "zig": "0.10.0-dev.315+4d05f2ae5"
}

// process.nextTick() is now implemented (currently only supports up to 4 arguments)
process.nextTick(() => console.log("second"));
console.log("first");

More stuff

import.meta in bun.js returns an object with file and dir

const {
  // import.meta.dir returns absolute path to the directory the script is in. sort of like __dirname
  dir,
  // import.meta.file returns absolute path to the script
  file,
} = import.meta;
  • queueMicrotask is implemented
  • If bun exits due to running out of file descriptors, bun will print some platform-specific instructions explaining how to fix it.
  • No longer need a ./ to run a script with bun.js, e.g. instead of bun ./foo.js, bun foo.js works now
  • Bun actually detects .mjs or .mts files now and treats them as ESM. Before it was reading them but ignoring the extension
  • Fixed a couple regressions that caused bun to start up slower, now it's back to about 3.5ms on macOS aarch64 and 0.5ms on linux amd64
  • Fixed a bug in the upgrade checker that would sometimes cause bun to crash, typically after about 30 seconds
  • Bun.gc(force) lets you manually run the garbage collector
  • Bun.shrink() runs a JavaScriptCore VM function that attempts to shrink the amount of memory used by JavaScriptCore
  • Bun.generateHeapSnapshot() returns a heap snapshot in a format I'm not entirely sure how to visualize yet

If you look hard enough, you'll also find a new subcommand for a very incomplete but fast Jest-like test runner. Hopefully will talk more about that next release or the one after.

Thanks

bun v0.0.66

04 Jan 07:04
Compare
Choose a tag to compare

To upgrade:

bun upgrade

These changes are since bun v0.0.56 (the previous release notes 13 days ago)

TLDR:

  • ~25% faster bun install when packages aren't downloaded
  • 5% faster JavaScript parser
  • Many bugfixes to bun install (but still more work to do!)
  • Improved filesystem watcher reliability on Linux
  • Docker images

bun install:

~25% faster when downloading lots of new packages. devDependencies were incorrectly being prioritized.

image

Plus:

  • bun add @scoped/package works now
  • >= ranges for package versions work correctly now
  • Fixed a bug in the retry logic for the HTTP client that would sometimes cause undefined memory to be returned. There still is more work to be done on the HTTP client to improve reliability.
  • On some Linux machines, bun install would error with error: SystemResources. This is an issue with the memlock limit that impacts io_uring. Now bun lowers memlock usage when this error returns until it finds a value that works
  • On Linux, bun had a dependency on glibc 2.32 which is too new for many machines. Now it depends on glibc 2.29
  • "no compatible binaries" error message was printing bytes instead of the string
  • Fixed a crash when removing the only dependency in package.json. When there are no dependencies in package.json, bun install will delete the lockfile
  • On Linux, when /tmp was mounted on a different filesystem, extracting packages failed with error: RenameAcrossMountPoints. Now bun tests if it can rename files from the temporary directory to the cache directory and chooses a different temporary directory if it cannot
  • Better error handling if lockfile is invalid or package.json is not found
  • bun install --production works better now. Just before installing, it clones the original lockfile in-memory and then removes any devDependencies listed in the root package.json.

bun run

  • Passing an absolute path to a JavaScript-like file will run the file with bun.js. Before, absolute paths were ignored

bun dev

Improved filesystem watcher reliability on Linux

bun now handles atomic file updates better in the filesystem watcher. To filesystem watchers, atomic file updates appear as a delete followed by a new file being moved to an existing directory. bun previously only noticed the delete. Most editors do not save atomically, but if vim swapfiles are enabled or if using replit, this may help.

Improved support for reverse-proxying bun

Due to same-origin policy, bun's HMR needs to use absolute URLs that match what the browser expects. Previously, to proxy bun you had to pass --origin to bun dev and it would maybe still not work for https. Now bun reads headers proxies send & what browsers send to determine which protocol, host, and/or origin is expected.

Misc:

  • If you use tailwind, it only warns once that @tailwind is not supported instead of on every single request to that .css file

bun-framework-next

  • A regression broke fetch() in SSR. This is fixed
  • The lack of a URL polyfill broke navigation in some cases. Now there is a URL polyfill. Eventually, bun.js will have this as a builtin implemented in native code.

bun.js

  • Add Bun.argv which returns string[] containing the CLI arguments used to open the currently running process. It is basically process.argv

bun bun

DevContainer

If you're interested in contributing to bun, you can now use a VSCode DevContainer to quickly setup the dev environment. Note that it currently requires at least 11 GB of ram in the dockerized OS to compile debug builds of bun.

Docker

bun now has automatic docker releases for Linux AMD64 compiled on every push to main. The tag name is jarredsumner/bun:${gitSHA}

Zig upgrade

bun is now using the latest version of Zig and LLVM 13, instead of a hacky patched version of Zig. This was a large change affecting basically every file in bun.

image

JavaScript Parser

5% faster JavaScript parser

image

Crash reporter

If bun crashes, it reports a little more metadata now and (on macOS) save a crash report to disk.

image

Sublime Text plugin for bun.lockb

@alexkuz wrote a Sublime Text plugin that opens bun.lockb (the lockfile for bun install) as a yarn.lock file and adds syntax highlighting. Thank you @alexkuz!

image

GitHub: https://github.com/alexkuz/sublime-yarn-lock

Thanks

Bun v0.0.56

21 Dec 22:45
Compare
Choose a tag to compare

To upgrade:

bun upgrade

bun install

Today is an exciting day. Introducing bun install – an incredibly fast npm client.

Before I get into perf numbers, consider this especially early.

  • workspaces not implemented yet
  • link: not implemented yet
  • github: not implemented yet
  • git: not implemented yet
  • Config file where you can set registry and auth tokens is not implemented yet. That means private packages won't really work yet (though it does read $npm_config_registry)
  • The lockfile format may change a little in the coming weeks (which would invalidate existing lockfiles)
  • postinstall will not be supported (probably won't be opt-in either). esbuild and turbo get special treatment I'm calling "native bin linking". I plan to write a more generalizable proposal for this that other npm clients can adopt to make shipping binary executables on npm faster & simpler
  • node-gyp isn't supported yet either, but that will be fixed.

Linux

100x faster npm install for incremental installs. In this case, only react is missing (the cleanup resets node_modules), each package manager has an up-to-date lockfile, and packages have previously downloaded before (disk cache)

20x faster than npm install when node_modules is empty. In this case, each package manager has an up-to-date lockfile and packages have also been downloaded before.

image

When there are no changes, bun install is 100x faster than npm install

image

macOS

Note: currently macOS installs are single-threaded & parallelism may help when there are > 100 packages, so these numbers may improve later

80x faster npm install for incremental installs.

image

4x faster npm install when there is no node_modules folder

image

When there are no changes, 80x faster than npm install

image

Autocomplete

Thanks to @evanwashere, bun add has autocomplete for the top 10,000 npm packages. It also searches your shell's history to complete from.

Screen_Recording_2021-12-19_at_11 32 08_PM

Fish completions:

image

Why is it faster?

I will do a longer write up on why it's faster. Zig is part of that, but a lot of work went into data layout, the lockfile format, the https client, the manifest cache format, and a lot of other stuff.

Bun v0.0.55

17 Dec 02:49
Compare
Choose a tag to compare

This release is mostly just bug fixes.

CommonJS <> ESM interop reliability improvements

Bun now preserves the behavior of live bindings when referencing bundled symbols. This fixes a number of subtle bugs in different packages.

This also updates the preferred extension order depending on how code is imported. Previously, .mjs files were ignored and that was silly. Now, when you use import and the path has no file extension, Bun will attempt to load .mjs or .mts before trying .js or .cjs

// CommonJS or `require`, `require.resolve`
// configurable via --extension-order CLI flag
pub const ExtensionOrder = [_]string{
    ".tsx",
    ".ts",
    ".jsx",
    ".cts",
    ".cjs",
    ".js",
    ".mjs",
    ".mts",
    ".json",
};

// ES Modules or `import`
pub const ModuleExtensionOrder = [_]string{
    ".tsx",
    ".jsx",
    ".mts",
    ".ts",
    ".mjs",
    ".js",
    ".cts",
    ".cjs",
    ".json",
};

Template literal parsing bug

Before, this code caused an assertion failure in Bun's JavaScript parser due to the function being defined in the template tag:

import styled from 'styled-components'

export const HoverableBox = styled.div.attrs<{
  disabled?: boolean
}>(({ disabled }) => ({
  cursor: disabled ? undefined : 'pointer',
}))<{ disabled?: boolean }>`
  ${({ disabled }) => (disabled ? 'pointer-events: none;' : '')}
`

The problem was related to when scopes for template literal tags were visited. This has been fixed.

try & require()

Previously, this code would produce a build error:

try {
  require("this-package-should-not-exist");
} catch (exception) {}

try {
  await import("this-package-should-not-exist");
} catch (exception) {}

import("this-package-should-not-exist").then(
  () => {},
  () => {}
);

In each of these cases, errors are caught at runtime, so it should not produce a build error.

Top-level await is now enabled

Top-level await will no longer error when targeting browsers, however you should know that since Bun does not transpile for backwards compatibility, you will need to be sure it is safe to use in the target environment.

Using module.exports with top-level await is undefined behavior

Bun v0.0.46

07 Nov 11:33
Compare
Choose a tag to compare

To upgrade:

bun upgrade

Like last release, this one is mostly bug fixes.

Better ZSH completions

The zsh completions now include flags, descriptions of subcommands, and "scripts" appear above package bins.

Also:

  • Filter out post.* and pre.* scripts from completions
  • Filter out .js files that start with . from completions
  • Filter out builtin commands from showing up at the top

The plugin for the typeahead here is zsh-autocomplete

macOS Mojave & macOS Catalina support

For absolutely no good reason, Bun was not able to run on any macOS version before macOS 11. Now bun should work for macOS Mojave and macOS Catalina.

However, I don't have a test machine so please let me know if it still doesn't work.

Bug fixes:

  • [resolver] Fix a bug with importing modules from packages using /*.extension in "exports" package.json and improve test coverage
  • [internal] Improve error messages when Bun fails to build due to a missing dependency
  • [zsh] zsh completions should more reliably find a directory to put them in
  • [zsh] Command not found: compdef previously appeared if zsh completions weren't installed. That's fixed now

Bun v0.0.45

05 Nov 08:58
Compare
Choose a tag to compare

To upgrade:

bun upgrade

This release is mostly bug fixes.

Improved fish completions

  • less noisy: no more file paths unless relevant and package executables are shown on bun run instead of bun
  • Before the description for a script was "script", now it's the actual script
  • If the first part of the script is NODE_OPTIONS=".*" (or any variation of NODE_OPTIONS), it's stripped out from the description. This is slightly nicer for larger repos that set --max-heap-size

bun
CleanShot 2021-11-05 at 01 40 27@2x

bun run:
CleanShot 2021-11-05 at 01 43 47@2x

Bug fixes

  • [bun run] Fix bug when running bun run yarn or a script that runs yarn --prod
  • [bun run] Fix a bug with how quotes & spaces were being passed through
  • [bun create] Fix npm install/yarn install for people using Volta (symlinks)
  • [bun run] Fix invoking node when using Volta (symlinks)
  • [JSX parser] Match esbuild behavior for JSX multi-line string literals and improve test coverage
  • [JSX parser] Fix regression with decoding JSX entities (e.g. &amp;) and improve test coverage
  • [JS parser] Decode input as WTF-8 instead of UTF-8. Insert a unicode replacement character for invalid unicode codepoints. Amongst other things, this fixes an error that occurred on require("faker")
  • [installer] Auto-detect when an Apple Silicon device is running on Rosetta 2 and download the arm64 version instead

Full Changelog: Jarred-Sumner/bun@bun-v0.0.44...bun-v0.0.45

Bun v0.0.44

03 Nov 10:22
Compare
Choose a tag to compare

To upgrade:

bun upgrade

Next.js 12

Bun works with Next.js 12 now. Before, it only supported 11.1.2. This includes support for React 18 (react@alpha). React Server Components is not supported yet, but it will be. I promise :)

CleanShot 2021-11-03 at 03 11 49@2x

Other stuff

  • (bun run) ZSH completions should auto-install correctly now. This will automatically apply when you run bun upgrade
  • (bun dev) Fixed a mistranspilation when using require from app code to a bundled module (e.g. require("relay-devtools"))
  • (bun bun) Fixed an issue with symlinked workspace packages when using alwaysBundle that prevented them from being correctly imported if enough levels of indirection were added
  • Fixed undefined behavior when invalid UTF-8 codepoints were inside source code text printed in an error message
  • (bun-macro-relay) Worked around a bug that could cause it to not correctly import graphql depending on the environment
  • (bun create) bumped the hardcoded Next.js version set to 12.0.2
  • Bun.js: rename Bun.sleep -> Bun.sleepSync

Full Changelog: Jarred-Sumner/bun@bun-v0.0.42...bun-v0.0.44

Bun v0.0.42

01 Nov 12:34
Compare
Choose a tag to compare

To upgrade:

bun upgrade

tab completions for bun run

bun run now has tab completions for zsh and fish that show scripts from package.json and bins from node_modules/.bin.

Install:

bun upgrade
bun completions 

Going forward, bun upgrade also updates completions, so you shouldn't have to do that again.

Bun.js

Bun now has a builtin "supports-color" polyfill, the package used by chalk to detect ANSI color support.

The TypeScript in this screenshot runs 2x faster in Bun.js than in Node.js:

image

Other stuff:

  • node-fetch & isomorphic-fetch polyfills work now. When an npm package imports node-fetch, Bun.js will automatically replace it with Bun's native implementation.
  • Bun.sleep(ms) lets you synchronously sleep. No promises
  • Fixed an edgecase with the CommonJS transform that affected export default (thank you @evanwashere for flagging)
  • Several more encoding issues specific to the JavaScriptCore integration were found & fixed, though there are a couple more I still need to fix.

JavaScript Lexer

  • Fixed a regression with \0 (and added an integration test)

Misc

  • --version now prints a newline at the end
  • -v is now shorthand for --version
  • Fixed spacing with the CLI help menu (thanks @KishanBagaria for flagging)
  • -u is now shorthand for --origin. Might rename that to --url in a future release.

Bun v0.0.41

30 Oct 11:32
Compare
Choose a tag to compare

To upgrade:

bun upgrade

What's new:

bun run:

bun run ./file.js now supports running JavaScript, TS, TSX, and JSX files using Bun.js. If you pass bun run a filepath to a .js, .jsx, .tsx, or .ts file, it will run it with Bun.js instead of saying "error: Missing script". This is very experimental!

Bun.js

Bun.js is Bun's JavaScript runtime environment.

  • Top-level await works now
  • performance.now() is implemented

Bug fixes

  • [.env loader] functions from bash were exported incorrectly due to parsing process environment variables similarly to .env files which is unnecessary. Now process environment variables are passed through without extra parsing
  • fetch() wasn't working due to a silly mistake. That's fixed

Bun v0.0.40

29 Oct 04:09
Compare
Choose a tag to compare

It's been a busy couple weeks.

Important: the bun-cli npm package is deprecated. It will not receive updates.

Please upgrade Bun by running:

# Remove the npm version of bun
npm uninstall -g bun-cli

# Install the new version
curl https://bun.sh/install | bash

For future upgrades:

bun upgrade

Now the fun part.

bun run

~35x faster package.json "scripts" runner, powered by Bun. Instead of npm run, try bun run.

Like npm run, bun run reads "scripts" in your package.json and runs the script in a shell with the same PATH changes as npm clients. Unlike npm clients, it's fast.

CleanShot 2021-10-28 at 19 29 21@2x

You can use bun run in projects that aren't using Bun for transpiling or bundling. It only needs a package.json file.

When scripts launch a Node.js process, bun run still beats npm run by 2x:

CleanShot 2021-10-28 at 19 37 43@2x

Why? Because npm clients launch an extra instance of Node.js. With npm run, you wait for Node.js to boot twice. With bun run, you wait once.

For maximum performance, if nested "scripts" run other npm tasks, bun run automatically runs the task with Bun instead. This means adding many tasks won't slow you down as much.

bun run supports lifecycle hooks you expect like pre and post and works when the package.json file is in a parent directory.

Two extra things:

  • bun run also adds any node_modules/.bin executables to the PATH, so e.g. if you're using Relay, you can do bun run relay-compiler and it will run the version of relay-compiler for the specific project.
  • bun run has builtin support for .env. It reads: .env.local, then .env.development || .env.production (respecting your NODE_ENV), and .env in the current directory or enclosing package.json's directory

Oh and you can drop the run:

CleanShot 2021-10-28 at 20 27 30@2x

Reliability

Lots of work went into improving the reliability of Bun over the last couple weeks.

Here's what I did:

  • Rewrote Bun's filesystem router for determinism and to support catch-all + optional-catch-all routes. This is an oversimplification, but the routes are sorted now
  • Improved testing coverage. Bun now has integration tests that check a simple Next.js app bundles & server-side prerenders successfully. If JavaScriptCore's JIT is not enabled while server-side rendering, the tests fail. Another integration test checks that a simple Create React App loads. It uses bun create to bootstrap the projects.
  • Fix all known unicode encoding & decoding bugs. Part of what makes parsing & printing JavaScript complicated is that JavaScript officially uses UTF-16 for strings, but the rest of the files on your computer likely use UTF-8. This gets extra complicated with server-side rendering because JavaScriptCore expects either a UTF-16 string for source code or a UTF-8 string. UTF-16 strings use about twice as much memory as UTF-8 strings. Instead of wasting memory, Bun escapes the strings where necessary (but only for server-side rendering)
  • Fixed several edgecases with the .env loader. .env values are now parsed as strings instead of something JSON-like

There's still a lot of work ahead, but Bun is getting better.

Sometimes, speed and reliability is a tradeoff. This time, it's not. Bun seems to be about 3% faster overall compared to the last version (v0.0.36). Why? Mostly due to many small changes to the lexer. Inlining iterators is good.