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
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 ....
| Package | Use instead |
|---|---|
core-js 2 | core-js 3 |
es5-shim, es6-shim, harmony-reflect | Nothing. Bun has what they add |
array.prototype.map/auto, set.prototype.union/auto, string.prototype.matchall/auto and the like | What the package exports, as in map(list, f) |
zone.js | Zoneless change detection in Angular |
chai.should() | expect or assert |
should, must | should/as-function, must/must |
timezone-mock | Set process.env.TZ |
sugar | Sugar.Array.sum(list), not Sugar.extend() |
ses | Freeze the prototypes with Object.freeze() |
asciidoctor 2 and 3 | asciidoctor 4 |
private | recast 0.20.4 or Babel 7, which dropped it |
@js-temporal/polyfill | Leave out the Date.prototype.toTemporalInstant = ... line of its README |
tar 6, minizlib 2 | tar 7 |
collections, prototype | No 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.
| Package | Use instead |
|---|---|
module-alias, tsconfig-paths | paths in tsconfig.json |
pirates, @babel/register, sucrase/register | Nothing. The build compiles TypeScript and JSX |
require-in-the-middle, @opentelemetry/instrumentation | No replacement. Nothing they patch is instrumented |
clear-module | No 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.
# 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/prerenderedFor 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.
export function greet(name: string): string {
return "hello " + name;
}{ "name": "greeter", "version": "1.0.0" }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){
"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.
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