Visitar URL original
Libraries | Bun Docs

Libraries

Which npm packages don't work with bun compile and what to use instead, the flags that frameworks need, and how to publish a package that keeps its types

Ahead-of-time compilation is experimental.

Nearly every npm package works with bun compile as it is. This page has the exceptions.

Packages that don't work#

These replace part of a built-in object, and stop with TypeError: Cannot assign to ....

PackageUse instead
core-js 2core-js 3
es5-shim, es6-shim, harmony-reflectNothing. Bun has what they add
array.prototype.map/auto, set.prototype.union/auto, string.prototype.matchall/auto and the likeWhat the package exports, as in map(list, f)
zone.jsZoneless change detection in Angular
chai.should()expect or assert
should, mustshould/as-function, must/must
timezone-mockSet process.env.TZ
sugarSugar.Array.sum(list), not Sugar.extend()
sesFreeze the prototypes with Object.freeze()
asciidoctor 2 and 3asciidoctor 4
privaterecast 0.20.4 or Babel 7, which dropped it
@js-temporal/polyfillLeave out the Date.prototype.toTemporalInstant = ... line of its README
tar 6, minizlib 2tar 7
collections, prototypeNo replacement

Adding to a built-in object is allowed. core-js 3, reflect-metadata, regenerator-runtime, colors, mockdate and sinon with its fake timers all work. So does next, which logs a line that begins with Failed to install when it starts.

These hook the module loader. The hook never runs for a compiled file. --no-aot doesn't change that.

PackageUse instead
module-alias, tsconfig-pathspaths in tsconfig.json
pirates, @babel/register, sucrase/registerNothing. The build compiles TypeScript and JSX
require-in-the-middle, @opentelemetry/instrumentationNo replacement. Nothing they patch is instrumented
clear-moduleNo replacement. A module runs once

A package that reads files beside its own code needs them embedded.

Frameworks#

Next.js and Angular put the paths of your pages together while the server runs, so the build doesn't find them. Pass the pages as entry points, and what the server reads from disk with --asset. The other frameworks only need the assets.

terminal
# Next.js with output: "standalone", in .next/standalone
bun compile ./server.js ".next/server/**/*.js" --asset .next --asset public
# Nuxt
bun compile ./.output/server/index.mjs --asset .output/public
# Astro
bun compile ./dist/server/entry.mjs --asset dist/client
# SvelteKit
bun compile ./build/index.js --asset build/client --asset build/prerendered

For Angular, the pages are the .mjs files beside server.mjs. If you use next/image, add --asset node_modules/@img, the folder that holds sharp.

Publish a package with its types#

Most packages ship JavaScript and .d.ts files, so the types inside their functions are gone. bun compile --library also writes your TypeScript, and a package.json whose exports point bun compile at it.

src/index.ts
export function greet(name: string): string {
  return "hello " + name;
}
package.json
{ "name": "greeter", "version": "1.0.0" }
terminal
bun compile --library
  index.js      87 bytes   (entry point)
  index.d.ts    53 bytes   (declaration)
  index.aot.ts  103 bytes  (aot source)
  package.json  430 bytes  (asset)
dist/package.json
{
  "exports": {
    ".": {
      "aot": "./index.aot.ts",
      "types": "./index.d.ts",
      "default": "./index.js"
    }
  }
}

bun compile loads index.aot.ts, and so do bun run, bun test and bun check with --aot. Everything else loads index.js.

To keep your own package.json, run bun build --dts and add the "aot" condition yourself. Put it first, because the first condition that matches wins.

The build of a program doesn't report type errors in your package, so run bun check before you publish, and try the package in an app. There, bun check --aot --all ./main.ts lists them too.

terminal
cd dist && bun pm pack            # greeter-1.0.0.tgz
cd ../../app && bun add ../greeter/dist/greeter-1.0.0.tgz
bun compile ./main.ts --explain   # shows where types are missing