Releases: oven-sh/bun
bun v0.0.68
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
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)
fs.existsSync
runs about 30% faster in bun.js (100,000 iterations)
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.
This is what the same error looks like in Node
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 ofbun ./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 collectorBun.shrink()
runs a JavaScriptCore VM function that attempts to shrink the amount of memory used by JavaScriptCoreBun.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
- @Andarist for adding module conditions when building for node
bun v0.0.66
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.
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 witherror: SystemResources
. This is an issue with thememlock
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 witherror: 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 returnsstring[]
containing the CLI arguments used to open the currently running process. It is basically process.argv
bun bun
- Improve error mesage when resolving entry point fails Jarred-Sumner/bun@11e3faa
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.
JavaScript Parser
5% faster JavaScript parser
Crash reporter
If bun crashes, it reports a little more metadata now and (on macOS) save a crash report to disk.
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!
GitHub: https://github.com/alexkuz/sublime-yarn-lock
Thanks
- Thanks @alexkuz and @afonsoduarte for fixing typos in the readme
- Thanks @ylukem for replacing all usages of
Bun
withbun
Bun v0.0.56
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 yetgithub:
not implemented yetgit:
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
andturbo
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.
When there are no changes, bun install
is 100x faster than npm install
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.
4x faster npm install when there is no node_modules folder
When there are no changes, 80x faster than npm install
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.
Fish completions:
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
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
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.*
andpre.*
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
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 ofbun
- 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 ofNODE_OPTIONS
), it's stripped out from the description. This is slightly nicer for larger repos that set--max-heap-size
Bug fixes
- [bun run] Fix bug when running
bun run yarn
or a script that runsyarn --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.
&
) 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
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 :)
Other stuff
- (
bun run
) ZSH completions should auto-install correctly now. This will automatically apply when you runbun upgrade
- (
bun dev
) Fixed a mistranspilation when usingrequire
from app code to a bundled module (e.g.require("relay-devtools")
) - (
bun bun
) Fixed an issue with symlinked workspace packages when usingalwaysBundle
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 importgraphql
depending on the environment - (
bun create
) bumped the hardcoded Next.js version set to12.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
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:
Other stuff:
node-fetch
&isomorphic-fetch
polyfills work now. When an npm package importsnode-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
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
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.
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:
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 anynode_modules/.bin
executables to the PATH, so e.g. if you're using Relay, you can dobun run relay-compiler
and it will run the version ofrelay-compiler
for the specific project.bun run
has builtin support for.env
. It reads:.env.local
, then.env.development
||.env.production
(respecting yourNODE_ENV
), and.env
in the current directory or enclosing package.json's directory
Oh and you can drop the run
:
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.