---
title: Bun v1.1.30
description: "Fixes 57 bugs (addressing 150 👍) Bun's CSS bundler is here (and very experimental). `bun publish` is a drop-in replacement for `npm publish`. `bun build --bytecode` compiles to bytecode leading to 2x faster start time. Bun.color() formats and normalizes colors. `bun pm whoami` prints your npm username. bun install reads $HOME/.npmrc. bun build --format=cjs outputs CommonJS modules. bun build --target=node now supports Node.js native addons. 30x faster crypto.privateEncrypt() & crypto.publicDecrypt(). Zombie process killer in bun test. --banner and --footer options in bun build. Bun.serve().stop() returns a promise. CryptoHasher now supports HMAC. Bugfixes for node:zlib, node:module, and node:buffer. Lots more bugfixes and Node.js compatibility improvements."
date: "2024-10-08T10:33:19.661Z"
author: jarred
---

{% callout %}
We're hiring [systems engineers](/careers) in San Francisco to build the future of JavaScript!
{% /callout %}

This release fixes 57 bugs (addressing 150 👍). Bun's CSS bundler is here (and very experimental). `bun publish` is a drop-in replacement for `npm publish`. `bun build --bytecode` compiles to bytecode leading to 2x faster start time. Bun.color() formats and normalizes colors. `bun pm whoami` prints your npm username. `bun install` reads `$HOME/.npmrc`. `bun build --format=cjs` outputs CommonJS modules. `bun build --target=node` now supports Node.js native addons. 30x faster `crypto.privateEncrypt()` & `crypto.publicDecrypt()`. Zombie process killer in bun test. `--banner` and `--footer` options in `bun build`. `Bun.serve().stop()` returns a promise. `Bun.CryptoHasher` now supports HMAC. Bugfixes for node:zlib, node:module, and node:buffer. Lots more bugfixes and Node.js compatibility improvements

#### To install Bun

{% codetabs %}

```sh#curl
$ curl -fsSL https://bun.sh/install | bash
```

```sh#npm
$ npm install -g bun
```

```sh#powershell
$ powershell -c "irm bun.sh/install.ps1|iex"
```

```sh#scoop
$ scoop install bun
```

```sh#brew
$ brew tap oven-sh/bun
$ brew install bun
```

```sh#docker
$ docker pull oven/bun
$ docker run --rm --init --ulimit memlock=-1:-1 oven/bun
```

{% /codetabs %}

#### To upgrade Bun

```sh
$ bun upgrade
```

## Experimental: CSS Parsing & bundling

Over the last two months, [@zackradisic](https://x.com/zack_overflow) built a CSS parser and bundler for Bun.

It's based on [@devongovett](https://x.com/devongovett)'s excellent [LightningCSS](https://github.com/parcel-bundler/lightningcss) parser, rewritten from Rust to Zig to vertically integrate into Bun's JavaScript & TypeScript parser, bundler, and runtime.

You can try it out today via `bun build` (CLI) or `Bun.build` (API) with the `--experimental-css` flag.

### CSS bundling

Bun's CSS bundler concatenates multiple CSS files and any assets referenced via `url`, `@import`, `@font-face`, etc into a single CSS file you can send to browsers, avoiding a waterfall of network requests.

```css#index.css
@import "foo.css";
@import "bar.css";
```

To try it out with `bun build` via CLI:

```sh#shell
$ bun build --experimental-css ./index.css
```

Those two CSS files become a single bundled CSS file:

```css#dist.css
/** foo.css */
.foo {
  background: red;
}

/** bar.css */
.bar {
  background: blue;
}
```

### Import .css files in JavaScript & TypeScript

Bun's CSS parser integrates with our JavaScript & TypeScript parser & bundler.

You can import .css files in JavaScript & TypeScript and an additional css entrypoint will be created that combines all the css files imported from a JavaScript/TypeScript module graph, along with any `@import` rules.

```ts#index.ts
import "./style.css";
import Component from "./MyComponent.tsx";

// ... rest of your app
```

Then, if `MyComponent.tsx` imports a CSS file, instead of adding extra .css files to the bundle, all the CSS imported per entrypoint is flattened into a single CSS file.

```sh#shell
$ bun build --experimental-css ./index.ts --outdir=dist
  index.js     0.10 KB
  index.css    0.10 KB
[5ms] bundle 4 modules
```

This outputs the following css file, which came from TypeScript imports:

```css#style.css
/* style.css */
.hello {
  background: red;
}

/* MyComponent.css */
.MyComponent {
  color: green;
}
```

### Bundle CSS with `Bun.build`:

We've also added support for programmatically bundling CSS with the `Bun.build` API. You can bundle both CSS and JavaScript in the same build with the same API.

```ts#api.ts
import { build } from "bun";

const results = await build({
  entrypoints: ["./index.css"],
  outdir: "./dist",
  experimentalCss: true,
});

console.log(results);
```

### How fast can it parse & bundle CSS?

We will release benchmarks once it's more stable, but I think you will be satisfied with the performance.

Huge thanks to [@zackradisic](https://github.com/zackradisic) for building this, and for @devongovett for his excellent LightningCSS library.

## `bun publish`: drop-in replacement for `npm publish`

You can use bun to publish npm packages via `bun publish`

```sh
$ bun publish

bun publish v1.1.30 (ecad797a)

packed 108B package.json
packed 3B README.md
packed 19B index.js

Total files: 3
Shasum: abd73b91b21057f0b07a58472077f5a3bbfb3e89
Integrity: sha512-aWkWikXiSXyR[...]Ubll4PQcEEoNw==
Unpacked size: 130B
Packed size: 254B
Tag: latest
Access: default
Registry: http://localhost:4873

+ lodash-2@1.0.0
```

`bun publish` is intended as a drop-in replacement for `npm publish`, and supports many of the same features like:

- Reading .npmrc files for authentication
- Packing tarballs, accounting for `.gitignore` and `.npmignore` files in multiple directories
- OTP / Two-factor authentication
- Handling various edgecases with package.json fields like `"bin"`, `"files"`, etc
- Handling missing README files carefully

Additionally, when using workspaces, `bun publish` will automatically rewrite dependency versions of workspace packages to point to the published version so that you can publish packages correctly that internally use `workspace:` dependencies.

Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!

## `bun pm whoami`

The new `bun pm whoami` command will print the current user's npm username.

```sh
$ bun pm whoami
bun
```

Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!

## Compile to bytecode for 2x faster startup time

`bun build` now supports bundling JavaScript & TypeScript to bytecode for a 2x faster startup time.

```sh
$ bun build --bytecode --compile ./index.ts
```

### Single-file bytecode executables

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">`bun build --bytecode --compile` makes eslint start 2x faster <a href="https://t.co/kFQ1KUJj2Z">pic.twitter.com/kFQ1KUJj2Z</a></p>&mdash; Jarred Sumner (@jarredsumner) <a href="https://twitter.com/jarredsumner/status/1840729983528137043?ref_src=twsrc%5Etfw">September 30, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

{% /raw %}

### Bytecode bundles

You can also use this without `--compile` if you would prefer individual files without the [standalone executable](https://bun.sh/docs/bundler/executables).

```sh
$ bun build --bytecode --outdir=./dist ./index.ts
```

This will output `.jsc` files alongside `.js` files. These `.jsc` contain the bytecode version of the file. Both are necessary to run in Bun, as the bytecode compilation doesn't currently compile async functions, generators, eval, and a handful of other edge cases.

The bytecode can be 8x larger than the source code, so this makes startup faster at a cost of increased disk space.

## CommonJS bundle output format

`bun build` now supports `--format=cjs` to output CommonJS bundles. Preivously, only `--format=esm` was supported.

This makes it easier to use `bun build` to build libraries & applications meant for Node.js in situations where CommonJS modules are easier to work with.

{% codetabs %}

```sh#shell.sh
$ bun build --format=cjs index.js
```

```js#index.js
// index.js
export default "Hello, world!";
```

```js#output.js
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __moduleCache = /* @__PURE__ */ new WeakMap;
var __toCommonJS = (from) => {
  var entry = __moduleCache.get(from), desc;
  if (entry)
    return entry;
  entry = __defProp({}, "__esModule", { value: true });
  if (from && typeof from === "object" || typeof from === "function")
    __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
      get: () => from[key],
      enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
    }));
  __moduleCache.set(from, entry);
  return entry;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, {
      get: all[name],
      enumerable: true,
      configurable: true,
      set: (newValue) => all[name] = () => newValue
    });
};

// index.js
var exports_site = {};
__export(exports_site, {
  default: () => site_default
});
module.exports = __toCommonJS(exports_site);
var site_default = "Hello, world!";
```

{% /codetabs %}

## Zombie process killer in `bun test`

On Linux and macOS, when a spawned process is not waited on, it's called a "zombie process".

Bun now automatically kills zombie processes from test timeouts in `bun test`.

When a test that spawns process(es) times out in `bun test`, if the process is not accessible outside of the test, then you would end up with a process that potentially never gets cleaned up if `bun test` were to exit soon after. This was especially noticable with tools like Puppeteer that spawn a browser instance. Lingering Chromium processes can cost you 100s of MBs of RAM and cause all sorts of issues.

Bun now internally tracks all processes spawned inside tests and if a test times out, Bun will automatically kill the process.

## Bundle `.node` files with `--target=node`

You can now bundle Node.js native modules using Bun and run those Node.js native modules in Node.js.

We fixed a bug that prevented `--target=node` from correctly bundling `.node` files, which are Node.js native modules. Previously, this was only supported with `--target=bun`, and now it's supported with `--target=node` as well.

## --banner and --footer options in `bun build`

You can now add a banner and footer above and below bundled output with `--banner` and `--footer` options in `bun build` and `Bun.build`.

Input:

{% codetabs %}

```sh#shell
$ bun build --banner "/* Hello, world! */" --footer "/* Goodbye! */" index.ts
```

```js#api.js
await Bun.build({
  entrypoints: ["./index.ts"],
  outdir: "./dist",
  banner: "/* Hello, world! */",
  footer: "/* Goodbye! */",
});
```

{% /codetabs %}

Output:

```js
/**
 * Hello, world!
 */
export default "Hello, world!";
/**
 * Goodbye!
 */
```

Huge thanks to [@versecafe](https://github.com/versecafe) for implementing this!

### `--registry` flag in `bun install`

You can now specify a custom registry from the command line when installing packages with `bun install`. You can use this flag by itself or with packages you want to add to your project.

```sh
# Install packages from a custom local registry instead of the default npm registry.
$ bun install --registry=http://localhost:4873/
# With packages
$ bun install zod --registry=http://localhost:4873/
```

You can continue to set the registry in `.npmrc` files, `bunfig.toml`, or via `NPM_CONFIG_REGISTRY` environment variable. This extra CLI flag is useful if you want to globally install a package from a private registry without having to set the registry in your `.npmrc` file or use a scoped package name.

## Bun.color() formats and normalizes colors

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun <br><br>Bun.color(input, outputFormat) leverages Bun&#39;s new CSS parser to parse, normalize, and convert colors into a variety of formats <a href="https://t.co/ffULyAVxHb">pic.twitter.com/ffULyAVxHb</a></p>&mdash; zack (in SF) (@zack_overflow) <a href="https://twitter.com/zack_overflow/status/1839407314329321561?ref_src=twsrc%5Etfw">September 26, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

{% /raw %}

## `stop()` in Bun.serve() returns a Promise

Bun's HTTP server API `Bun.serve()` now returns a Promise from `server.stop()` which resolves when all connections are closed.

This lets you use `await server.stop()` to wait for all the connections to close without abruptly closing them.

```js
const server = Bun.serve({
  port: 3000,
  async fetch(req) {
    return new Response("Hello, world!");
  },
});

await server.stop();
```

## HMAC in `Bun.CryptoHasher`

`Bun.CryptoHasher` can now be used to compute HMAC digests. To do so, pass the key to the constructor.

```js
import { CryptoHasher } from "bun";
const hasher = new CryptoHasher("sha1", "secret-key");
const hash = hasher
  .update("message")
  // This creates the HMAC signature
  .digest("hex");

console.log(hash); // 48de2656eac2c9c21b04faeec4f1be9672ef53c1
```

## bun install reads $HOME/.npmrc now

`bun install` now reads `$HOME/.npmrc` files for authentication if no other registry is specified.

Previously, only `.npmrc` in the current directory was read. Now, `$HOME/.npmrc` is also read if no `.npmrc` is found in the current package.json directory.

Thanks to [@robertshuford](https://github.com/robertshuford) for implementing this!

## Bundler fixes

### Fixed: top-level `await` bug in `bun build`

A bug that could cause spurious top-level `await` errors in `bun build` has been fixed, thanks to [@snoglobe](https://github.com/snoglobe)!

### Fixed: importing JSON with unicode characters in `bun build`

Importing JSON with unicode characters now works correctly with `bun build`. Bun was previously incorrectly converting the encoding of strings from JSON, causing unicode characters to be interpreted in the wrong encoding.

```json
// test.json
{
  "测试a": "b"
}
```

```js
// test.js
import data from "./test.json";
console.log(data["测试" + "a"]); // b
```

Thanks to [@snoglobe](https://github.com/snoglobe)!

## Node.js compatibility improvements

### 30x faster crypto.privateEncrypt() & crypto.publicDecrypt()

`crypto.privateEncrypt()` and `crypto.publicDecrypt()` in Bun are now powered by BoringSSL, which leads to a 30x performance improvement to these functions over the previous JavaScript polyfill implementation.

After:

```sh
benchmark                                  time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------------- -----------------------------
RSA sign RSA_PKCS1_PADDING round-trip     832 µs/iter       (816 µs … 915 µs)    834 µs    893 µs    915 µs
```

Before:

```sh
benchmark                                  time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------------- -----------------------------
RSA sign RSA_PKCS1_PADDING round-trip  26'997 µs/iter (26'657 µs … 27'551 µs) 27'119 µs 27'551 µs 27'551 µs
```

Thanks to [@wpaulino](https://github.com/wpaulino) for the fix!

### `require("cluster")` gets 6ms faster

The time it takes to `require("cluster")` has been reduced by 6ms, thanks to [@nektro](https://github.com/nektro)

Previously:

```sh
$ bun-1.1.29 --print 'console.time("require(`cluster`)");require(`cluster`);console.timeEnd("require(`cluster`)");' # Old
[7.62ms] require(`cluster`)
```

Now:

```sh
$ bun --print 'console.time("require(`cluster`)");require(`cluster`);console.timeEnd("require(`cluster`)");' # New
[1.39ms] require(`cluster`)
```

### Fixed: Buffer.alloc bug with 2nd argument bug

A bug when Buffer.alloc was passed an empty string as the second argument has been fixed.

Thanks to [@nektro](https://github.com/nektro) for the fix!

### Fixed: Several node:zlib issues

Bun's node:zlib implementation now passes many more Node.js tests, thanks to [@nektro](https://github.com/nektro)! This addresses issues with Sharp/Jimp, Zip.js, some GPRC libraries, pubnub, and more.

Thanks to [@nektro](https://github.com/nektro) for the fix!

### Fixed: Prisma not waiting for promises before exiting

A bug in our NAPI implementation could cause Prisma to not wait for promises in queries before the Bun process exits.

Thanks to [@190n](https://github.com/190n) for the fix!

### Fixed: Missing exports in `node:module`

A handful of missing exports in `node:module` have been added:

- `_preloadModules` was previously undefined. Now it does nothing
- `_debug` & `_pathCache` was previously `undefined`
- `enableCompileCache` and `getCompileCache` were previously undefined
- `__resolveFilename` and `_resolveFilename` were previously both defined, now only `_resolveFilename` is defined

### Fixed: console.log on `require.cache`

Previously, `console.log(require.cache)` would print an empty object. Now it prints the cache.

```js
// Old
{}

// New
{
  "/path/to/module": Module {
    id: "/path/to/module",
    exports: {},
    parent: null,
    filename: "/path/to/module.js",
    loaded: false,
    children: [],
    paths: []
  }
}
```

### Fixed: `process.cwd()` returning the wrong path on Windows for the root of a drive

A regression has been fixed where `process.cwd()` would return an incorrect path on Windows if the current working directory was at the root of a drive. For example, if the current working directory was `C:\`, `process.cwd()` would return `C:` instead of `C:\`.

### Fixed: 2 rare crashes in Bun.spawn()

Two rare crashes in `Bun.spawn()` have been fixed. One was a regression from Bun v1.1.25. It sometimes happened when the subprocess was garbage collected before referencing stdin in certain cases.

### Prototype pollution mitigation

To make [prototype pollution](https://en.wikipedia.org/wiki/Prototype_pollution) more difficult to exploit in Bun's APIs, Bun APIs now ignore the `Object` prototype when reading values from objects and functions in natively implemented Bun APIs (such as `fetch`, `Request`, `Response`, etc).

Previously, the following code would cause `glob.scanSync` to follow symlinks:

```ts
import { Glob } from "bun";
const glob = new Glob("*.ts");
Object.defineProperty(Object.prototype, "followSymlinks", {
  value: true,
  writable: true,
  configurable: true,
  enumerable: true,
});
const second = glob.scanSync({
  cwd: path.join(dir, "abc"),
  onlyFiles: true,
});
```

Now, since the `Object.prototype` is ignored, this attack is mitigated. We've done this for nearly all Bun APIs implemented in Zig.

This doesn't fully prevent prototype pollution attacks, but it does make them more difficult to exploit in Bun APIs. Thanks to [@lirantal](https://github.com/lirantal) for the report!

### Fixed: `bun add` incorrectly adding relative paths to tarballs in workspaces

A bug was fixed causing `bun add` to fail to add local tarball packages to workspaces. This would happen because bun was using the workspace root as the base path rather than the current workspace package the tarball would be added to.

## Thanks to 17 contributors!

- [@190n](https://github.com/190n)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@lewismiddleton](https://github.com/lewismiddleton)
- [@matubu](https://github.com/matubu)
- [@metonym](https://github.com/metonym)
- [@mjomble](https://github.com/mjomble)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@robertshuford](https://github.com/robertshuford)
- [@snoglobe](https://github.com/snoglobe)
- [@versecafe](https://github.com/versecafe)
- [@wpaulino](https://github.com/wpaulino)
- [@Xmarmalade](https://github.com/Xmarmalade)
- [@zackradisic](https://github.com/zackradisic)
