aboutsummaryrefslogtreecommitdiff
path: root/docs/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'docs/runtime')
-rw-r--r--docs/runtime/hot.md93
-rw-r--r--docs/runtime/index.md286
-rw-r--r--docs/runtime/loaders.md28
-rw-r--r--docs/runtime/modules.md259
-rw-r--r--docs/runtime/nodejs.md682
-rw-r--r--docs/runtime/plugins.md245
-rw-r--r--docs/runtime/streams.md5
-rw-r--r--docs/runtime/web-apis.md300
8 files changed, 1893 insertions, 5 deletions
diff --git a/docs/runtime/hot.md b/docs/runtime/hot.md
new file mode 100644
index 000000000..bdd376011
--- /dev/null
+++ b/docs/runtime/hot.md
@@ -0,0 +1,93 @@
+{% callout %}
+🚧 **Experimental** — Introduced in Bun v0.2.0.
+{% /callout %}
+Use `bun --hot` to enable hot reloading when executing code with Bun.
+
+```bash
+$ bun --hot server.ts
+```
+
+Starting from the entrypoint (`server.ts` in the example above), Bun builds a registry of all imported source files (excluding those in `node_modules`) and watches them for changes. When a change is detected, Bun performs a "soft reload". All files are re-evaluated, but all global state (notably, the `globalThis` object) is persisted.
+
+```ts#server.ts
+globalThis.count = globalThis.count ?? 0;
+console.log(`Reloaded ${globalThis.count} times`);
+globalThis.count++;
+
+setInterval(function () {}, 1000000);
+```
+
+If you run this file with `bun --hot server.ts`, you'll see the reload count increment every time you save the file. The call to `setInterval` is there to prevent the process from exiting.
+
+```bash
+$ bun --hot index.ts
+Reloaded 1 times
+Reloaded 2 times
+Reloaded 3 times
+```
+
+Traditional file watchers like `nodemon` restart the entire process, so HTTP servers and other stateful objects are lost. By contrast, `bun --hot` is able to reflect the updated code without restarting the process.
+
+### HTTP servers
+
+Bun provides the following simplified API for implementing HTTP servers. Refer to [API > HTTP](/docs/api/http) for full details.
+
+```ts#server.ts
+globalThis.count = globalThis.count ?? 0;
+globalThis.reloadCount++;
+
+export default {
+ fetch(req: Request) {
+ return new Response(`Reloaded ${globalThis.count} times`);
+ },
+ port: 3000,
+};
+```
+
+The file above is simply exporting an object with a `fetch` handler defined. When this file is executed, Bun interprets this as an HTTP server and passes the exported object into `Bun.serve`.
+
+Unlike an explicit call to `Bun.serve`, the object-based syntax works out of the box with `bun --hot`. When you save the file, your HTTP server be reloaded with the updated code without the process being restarted. This results in seriously fast refresh speeds.
+
+{% image src="https://user-images.githubusercontent.com/709451/195477632-5fd8a73e-014d-4589-9ba2-e075ad9eb040.gif" alt="Bun vs Nodemon refresh speeds" caption="Bun on the left, Nodemon on the right." /%}
+
+For more fine-grained control, you can use the `Bun.serve` API directly and handle the server reloading manually.
+
+```ts#server.ts
+import type {Serve} from "bun";
+
+globalThis.count = globalThis.count ?? 0;
+globalThis.reloadCount++;
+
+// define server parameters
+const serverOptions: Serve = {
+ port: 3000,
+ fetch(req) {
+ return new Response(`Reloaded ${globalThis.count} times`);
+ }
+};
+
+if (!globalThis.server) {
+ globalThis.server = Bun.serve(serverOptions);
+} else {
+ // reload server
+ globalThis.server.reload(serverOptions);
+}
+```
+
+{% callout %}
+**Note** — In a future version of Bun, support for Vite's `import.meta.hot` is planned to enable better lifecycle management for hot reloading and to align with the ecosystem.
+
+{% /callout %}
+
+{% details summary="Implementation `details`" %}
+
+On reload, Bun:
+
+- Resets the internal `require` cache and ES module registry (`Loader.registry`)
+- Runs the garbage collector synchronously (to minimize memory leaks, at the cost of runtime performance)
+- Re-transpiles all of your code from scratch (including sourcemaps)
+- Re-evaluates the code with JavaScriptCore
+
+This implementation isn't particularly optimized. It re-transpiles files that haven't changed. It makes no attempt at incremental compilation. It's a starting point.
+
+{% /details %}
diff --git a/docs/runtime/index.md b/docs/runtime/index.md
new file mode 100644
index 000000000..29ea99c0f
--- /dev/null
+++ b/docs/runtime/index.md
@@ -0,0 +1,286 @@
+Bun is a new JavaScript runtime designed to be a faster, leaner, more modern replacement for Node.js.
+
+## Speed
+
+Bun is designed to start fast and run fast. It's transpiler and runtime are written in Zig, a modern, high-performance language. On Linux, this translates into startup times [4x faster](https://twitter.com/jarredsumner/status/1499225725492076544) than Node.js. Performance sensitive APIs like `Buffer`, `fetch`, and `Response` are heavily profiled and optimized. Under the hood Bun uses the [JavaScriptCore engine](https://developer.apple.com/documentation/javascriptcore), which is developed by Apple for Safari. It starts and runs faster than V8, the engine used by Node.js and Chromium-based browsers.
+
+## File types
+
+Bun natively supports TypeScript and JSX out of the box.
+
+```bash
+$ bun server.tsx
+```
+
+<!-- Before execution, Bun internally transforms all source files to vanilla JavaScript using its fast native transpiler. The transpiler looks at the files extension to determine how to handle it. -->
+
+<!--
+
+every file before execution. It's transpiler can directly run TypeScript and JSX `{.js|.jsx|.ts|.tsx}` files directly. During execution, Bun internally transpiles all files (including `.js` files) to vanilla JavaScript with it's fast native transpiler. -->
+
+<!-- A loader determines how to map imports &amp; file extensions to transforms and output. -->
+
+<!-- Currently, Bun implements the following loaders: -->
+
+<!-- {% table %}
+
+- Extension
+- Transforms
+- Output (internal)
+
+---
+
+- `.js`
+- JSX + JavaScript
+- `.js`
+
+---
+
+- `.jsx`
+- JSX + JavaScript
+- `.js`
+
+---
+
+- `.ts`
+- TypeScript + JavaScript
+- `.js`
+
+---
+
+- `.tsx`
+- TypeScript + JSX + JavaScript
+- `.js`
+
+---
+
+- `.mjs`
+- JavaScript
+- `.js`
+
+---
+
+- `.cjs`
+- JavaScript
+- `.js`
+
+---
+
+- `.mts`
+- TypeScript
+- `.js`
+
+---
+
+- `.cts`
+- TypeScript
+- `.js`
+
+
+{% /table %} -->
+
+Source files can import a `*.json` or `*.toml` file to load its contents as a plain old JavaScript object.
+
+```ts
+import pkg from "./package.json";
+import bunfig from "./bunfig.toml";
+```
+
+As of v0.5.2, experimental support has been for the [WebAssembly System Interface](https://github.com/WebAssembly/WASI) (WASI), you can run `.wasm` binaries.
+
+```bash
+$ bun ./my-wasm-app.wasm
+# if the filename doesn't end with ".wasm"
+$ bun run ./my-wasm-app.whatever
+```
+
+{% callout %}
+**Note** — WASI support is based on [wasi-js](https://github.com/sagemathinc/cowasm/tree/main/packages/wasi-js). Currently, it only supports WASI binaries that use the `wasi_snapshot_preview1` or `wasi_unstable` APIs. Bun's implementation is not optimized for performance, but if this feature gets popular, we'll definitely invest time in making it faster.
+{% /callout %}
+
+Support for additional file types can be implemented with [Plugins](/docs/runtime/plugins).
+
+## Node.js compatibility
+
+Long-term, Bun aims for complete Node.js compatibility. Most Node.js packages already work with Bun out of the box, but certain low-level APIs like `dgram` are still unimplemented. Track the current compatibility status at [Runtime > Node.js API](/docs/runtime/nodejs).
+
+Bun implements the Node.js module resolution algorithm, so dependencies can still be managed with `package.json`, `node_modules`, and CommonJS-style imports.
+
+{% callout %}
+**Note** — We recommend using Bun's [built-in package manager](/docs/cli/install) for a performance boost over other npm clients.
+{% /callout %}
+
+## Web-standard
+
+<!-- When prudent, Bun attempts to implement Web-standard APIs instead of introducing new APIs. Refer to [Runtime > Web APIs](/docs/web-apis) for a list of Web APIs that are available in Bun. -->
+
+Some Web APIs aren't relevant in the context of a server-first runtime like Bun, such as the [DOM API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API#html_dom_api_interfaces) or [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API). Many others, though, are broadly useful outside of the browser context; when possible, Bun implements these Web-standard APIs instead of introducing new APIs.
+
+The following Web APIs are partially or completely supported.
+
+{% table %}
+
+---
+
+- HTTP
+- [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
+
+---
+
+- URLs
+- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
+
+---
+
+- Streams
+- [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy) [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy) and associated classes
+
+---
+
+- Blob
+- [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
+
+---
+
+- WebSockets
+- [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
+
+---
+
+- Encoding and decoding
+- [`atob`](https://developer.mozilla.org/en-US/docs/Web/API/atob) [`btoa`](https://developer.mozilla.org/en-US/docs/Web/API/btoa) [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder)
+
+---
+
+- Timeouts
+- [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout)
+
+---
+
+- Intervals
+- [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval)[`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval)
+
+---
+
+- Crypto
+- [`crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)
+ [`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)
+
+---
+
+- Debugging
+
+- [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console) [`performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance)
+
+---
+
+- Microtasks
+- [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
+
+---
+
+- Errors
+- [`reportError`](https://developer.mozilla.org/en-US/docs/Web/API/reportError) [`ResolveError`](https://developer.mozilla.org/en-US/docs/Web/API/ResolveError)
+ [`BuildError`](https://developer.mozilla.org/en-US/docs/Web/API/BuildError)
+
+---
+
+- User interaction
+- [`alert`](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert) [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) [`prompt`](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) (intended for interactive CLIs)
+
+<!-- - Blocking. Prints the alert message to terminal and awaits `[ENTER]` before proceeding. -->
+<!-- - Blocking. Prints confirmation message and awaits `[y/N]` input from user. Returns `true` if user entered `y` or `Y`, `false` otherwise.
+- Blocking. Prints prompt message and awaits user input. Returns the user input as a string. -->
+
+---
+
+- Realms
+- [`ShadowRealm`](https://github.com/tc39/proposal-shadowrealm)
+
+---
+
+- Events
+- [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget)
+ [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event) [`ErrorEvent`](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent) [`CloseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent)
+
+---
+
+{% /table %}
+
+## Bun-native APIs
+
+Bun exposes a set of Bun-specific APIs on the `Bun` global object and through a number of built-in modules. These APIs represent the canonical "Bun-native" way to perform some common development tasks. They are all heavily optimized for performance. Click the link in the left column to view the associated documentation.
+
+{% table %}
+
+- Topic
+- APIs
+
+---
+
+- [HTTP](/docs/api/http)
+- `Bun.serve`
+
+---
+
+- [File I/O](/docs/api/file-io)
+- `Bun.file` `Bun.write`
+
+---
+
+- [Processes](/docs/api/spawn)
+- `Bun.spawn` `Bun.spawnSync`
+
+---
+
+- [TCP](/docs/api/tcp)
+- `Bun.listen` `Bun.connect`
+
+---
+
+- [Transpiler](/docs/api/transpiler)
+- `Bun.Transpiler`
+
+---
+
+- [Routing](/docs/api/file-system-router)
+- `Bun.FileSystemRouter`
+
+---
+
+- [HTMLRewriter](/docs/api/html-rewriter)
+- `HTMLRewriter`
+
+---
+
+- [Utils](/docs/api/utils)
+- `Bun.peek` `Bun.which`
+
+---
+
+- [SQLite](/docs/api/sqlite)
+- `bun:sqlite`
+
+---
+
+- [FFI](/docs/api/ffi)
+- `bun:ffi`
+
+---
+
+- [DNS](/docs/api/dns)
+- `bun:dns`
+
+---
+
+- [Testing](/docs/api/test)
+- `bun:test`
+
+---
+
+- [Node-API](/docs/api/node-api)
+- `Node-API`
+
+---
+
+{% /table %}
diff --git a/docs/runtime/loaders.md b/docs/runtime/loaders.md
new file mode 100644
index 000000000..c7977534c
--- /dev/null
+++ b/docs/runtime/loaders.md
@@ -0,0 +1,28 @@
+A loader determines how to map imports &amp; file extensions to transforms and output.
+
+Currently, Bun implements the following loaders:
+
+| Input | Loader | Output |
+| ----- | ----------------------------- | ------ |
+| .js | JSX + JavaScript | .js |
+| .jsx | JSX + JavaScript | .js |
+| .ts | TypeScript + JavaScript | .js |
+| .tsx | TypeScript + JSX + JavaScript | .js |
+| .mjs | JavaScript | .js |
+| .cjs | JavaScript | .js |
+| .mts | TypeScript | .js |
+| .cts | TypeScript | .js |
+| .toml | TOML | .js |
+| .css | CSS | .css |
+| .env | Env | N/A |
+| .\* | file | string |
+
+Everything else is treated as `file`. `file` replaces the import with a URL (or a path).
+
+You can configure which loaders map to which extensions by passing `--loaders` to `bun`. For example:
+
+```sh
+$ bun --loader=.js:js
+```
+
+This will disable JSX transforms for `.js` files.
diff --git a/docs/runtime/modules.md b/docs/runtime/modules.md
new file mode 100644
index 000000000..f10dad378
--- /dev/null
+++ b/docs/runtime/modules.md
@@ -0,0 +1,259 @@
+Module resolution in JavaScript is a complex topic.
+
+The ecosystem is currently in the midst of a years-long transition from CommonJS modules to native ES modules. TypeScript enforces its own set of rules around import extensions that aren't compatible with ESM. Different build tools support path re-mapping via disparate non-compatible mechanisms.
+
+Bun aims to provide a consistent and predictable module resolution system that just works. Unfortunately it's still quite complex.
+
+## Syntax
+
+Consider the following files.
+
+{% codetabs %}
+
+```ts#index.ts
+import { hello } from "./hello";
+
+hello();
+```
+
+```ts#hello.ts
+export function hello() {
+ console.log("Hello world!");
+}
+```
+
+{% /codetabs %}
+
+When we run `index.ts`, it prints "Hello world".
+
+```bash
+$ bun index.ts
+Hello world!
+```
+
+In this case, we are importing from `./hello`, a relative path with no extension. To resolve this import, Bun will check for the following files in order:
+
+- `./hello.ts`
+- `./hello.tsx`
+- `./hello.js`
+- `./hello.mjs`
+- `./hello.cjs`
+- `./hello/index.ts`
+- `./hello/index.js`
+- `./hello/index.json`
+- `./hello/index.mjs`
+
+Import paths are case-insensitive.
+
+```ts#index.ts
+import { hello } from "./hello";
+import { hello } from "./HELLO";
+import { hello } from "./hElLo";
+```
+
+Import paths can optionally include extensions. If an extension is present, Bun will only check for a file with that exact extension.
+
+```ts#index.ts
+import { hello } from "./hello";
+import { hello } from "./hello.ts"; // this works
+```
+
+There is one exception: if you import `from "*.js{x}"`, Bun will additionally check for a matching `*.ts{x}` file, to be compatible with TypeScript's [ES module support](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#new-file-extensions).
+
+```ts#index.ts
+import { hello } from "./hello";
+import { hello } from "./hello.ts"; // this works
+import { hello } from "./hello.js"; // this also works
+```
+
+Bun supports both ES modules (`import`/`export` syntax) and CommonJS modules (`require()`/`module.exports`). The following CommonJS version would also work in Bun.
+
+{% codetabs %}
+
+```ts#index.js
+const { hello } = require("./hello");
+
+hello();
+```
+
+```ts#hello.js
+function hello() {
+ console.log("Hello world!");
+}
+
+exports.hello = hello;
+```
+
+{% /codetabs %}
+
+That said, using CommonJS is discouraged in new projects.
+
+## Resolution
+
+Bun implements the Node.js module resolution algorithm, so you can import packages from `node_modules` with a bare specifier.
+
+```ts
+import { stuff } from "foo";
+```
+
+The full specification of this algorithm are officially documented in the [Node.js documentation](https://nodejs.org/api/modules.html); we won't rehash it here. Briefly: if you import `from "foo"`, Bun scans up the file system for a `node_modules` directory containing the package `foo`.
+
+Once it finds the `foo` package, Bun reads the `package.json` to determine how the package should be imported. Unless `"type": "module"` is specified, Bun assumes the package is using CommonJS and transpiles into a synchronous ES module internally. To determine the package's entrypoint, Bun first reads the `exports` field in and checks the following conditions in order:
+
+```jsonc#package.json
+{
+ "name": "foo",
+ "exports": {
+ "bun": "./index.js", // highest priority
+ "worker": "./index.js",
+ "module": "./index.js",
+ "node": "./index.js",
+ "browser": "./index.js",
+ "default": "./index.js" // lowest priority
+ }
+}
+```
+
+Bun respects subpath [`"exports"`](https://nodejs.org/api/packages.html#subpath-exports) and [`"imports"`](https://nodejs.org/api/packages.html#imports). Specifying any subpath in the `"exports"` map will prevent other subpaths from being importable.
+
+```jsonc#package.json
+{
+ "name": "foo",
+ "exports": {
+ ".": "./index.js",
+ "./package.json": "./package.json" # subpath
+ }
+}
+```
+
+{% callout %}
+**Shipping TypeScript** — Note that Bun supports the special `"bun"` export condition. If your library is written in TypeScript, you can publish your (un-transpiled!) TypeScript files to `npm` directly. If you specify your package's `*.ts` entrypoint in the `"bun"` condition, Bun will directly import and execute your TypeScript source files.
+{% /callout %}
+
+If `exports` is not defined, Bun falls back to `"module"` (ESM imports only) then [`"main"`](https://nodejs.org/api/packages.html#main).
+
+```json#package.json
+{
+ "name": "foo",
+ "module": "./index.js",
+ "main": "./index.js"
+}
+```
+
+## Path re-mapping
+
+In the spirit of treating TypeScript as a first-class citizen, the Bun runtime will re-map import paths according to the [`compilerOptions.paths`](https://www.typescriptlang.org/tsconfig#paths) field in `tsconfig.json`. This is a major divergence from Node.js, which doesn't support any form of import path re-mapping.
+
+```jsonc#tsconfig.json
+{
+ "compilerOptions": {
+ "paths": {
+ "config": ["./config.ts"], // map specifier to file
+ "components/*": ["components/*"], // wildcard matching
+ }
+ }
+}
+```
+
+If you aren't a TypeScript user, you can create a [`jsconfig.json`](https://code.visualstudio.com/docs/languages/jsconfig) in your project root to achieve the same behavior.
+
+## Bun-style resolution
+
+{% callout %}
+**Note** — Added in Bun v0.3.0
+{% /callout %}
+
+If no `node_modules` directory is found in the working directory or higher, Bun will abandon Node.js-style module resolution in favor of the **Bun module resolution algorithm**.
+
+Under Bun-style module resolution, all imported packages are auto-installed on the fly into a [global module cache](/docs/cli/install#global-cache) during execution (the same cache used by [`bun install`](/docs/cli/install)).
+
+```ts
+import { foo } from "foo"; // install `latest` version
+
+foo();
+```
+
+The first time you run this script, Bun will auto-install `"foo"` and cache it. The next time you run the script, it will use the cached version.
+
+### Version resolution
+
+To determine which version to install, Bun follows the following algorithm:
+
+1. Check for a `bun.lockb` file in the project root. If it exists, use the version specified in the lockfile.
+2. Otherwise, scan up the tree for a `package.json` that includes `"foo"` as a dependency. If found, use the specified semver version or version range.
+3. Otherwise, use `latest`.
+
+### Cache behavior
+
+Once a version or version range has been determined, Bun will:
+
+1. Check the module cache for a compatible version. If one exists, use it.
+2. When resolving `latest`, Bun will check if `package@latest` has been downloaded and cached in the last _24 hours_. If so, use it.
+3. Otherwise, download and install the appropriate version from the `npm` registry.
+
+### Installation
+
+Packages are installed and cached into `<cache>/<pkg>@<version>`, so multiple versions of the same package can be cached at once. Additional, a symlink is created under `<cache>/<pkg>/<version>` to make it faster to look up all versions of a package exist in the cache.
+
+### Version specifiers
+
+This entire resolution algorithm can be short-circuited by specifying a version or version range directly in your import statement.
+
+```ts
+import { z } from "zod@3.0.0"; // specific version
+import { z } from "zod@next"; // npm tag
+import { z } from "zod@^3.20.0"; // semver range
+```
+
+### Benefits
+
+This auto-installation approach is useful for a few reasons:
+
+- **Space efficiency** — Each version of a dependency only exists in one place on disk. This is a huge space and time savings compared to redundant per-project installations.
+- **Portability** — To share simple scripts and gists, your source file is _self-contained_. No need to `zip` together a directory containing your code and config files. With version specifiers in `import` statements, even a `package.json` isn't necessary.
+- **Convenience** — There's no need to run `npm install` or `bun install` before running a file or script. Just `bun run` it.
+- **Backwards compatibility** — Because Bun still respects the versions specified in `package.json` if one exists, you can switch to Bun-style resolution with a single command: `rm -rf node_modules`.
+
+### Limitations
+
+- No Intellisense. TypeScript auto-completion in IDEs relies on the existence of type declaration files inside `node_modules`. We are investigating various solutions to this.
+- No [patch-package](https://github.com/ds300/patch-package) support
+
+<!-- - The implementation details of Bun's install cache will change between versions. Don't think of it as an API. To reliably resolve packages, use Bun's builtin APIs (such as `Bun.resolveSync` or `import.meta.resolve`) instead of relying on the filesystem directly. Bun will likely move to a binary archive format where packages may not correspond to files/folders on disk at all - so if you depend on the filesystem structure instead of the JavaScript API, your code will eventually break. -->
+
+<!-- ### Customizing behavior
+
+To prefer locally-installed versions of packages. Instead of checking npm for latest versions, you can pass the `--prefer-offline` flag to prefer locally-installed versions of packages.
+
+```bash
+$ bun run --prefer-offline my-script.ts
+```
+
+This will check the install cache for installed versions of packages before checking the npm registry. If no matching version of a package is installed, only then will it check npm for the latest version.
+
+#### Prefer latest
+
+To always use the latest version of a package, you can pass the `--prefer-latest` flag.
+
+```bash
+$ bun run --prefer-latest my-script.ts
+``` -->
+
+### FAQ
+
+{% details summary="How is this different from what pnpm does?" %}
+
+With pnpm, you have to run `pnpm install`, which creates a `node_modules` folder of symlinks for the runtime to resolve. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time. Bun also doesn't create a `node_modules` folder.
+
+{% /details %}
+
+{% details summary="How is this different from Yarn Plug'N'Play does?" %}
+With Yarn, you must run `yarn install` before you run a script. By contrast, Bun resolves dependencies on the fly when you run a file; there's no need to run any `install` command ahead of time.
+
+Yarn Plug'N'Play also uses zip files to store dependencies. This makes dependency loading [slower at runtime](https://twitter.com/jarredsumner/status/1458207919636287490), as random access reads on zip files tend to be slower than the equivalent disk lookup.
+{% /details %}
+
+{% details summary="How is this different from what Deno does?" %}
+
+Deno requires an `npm:` specifier before each npm `import`, lacks support for import maps via `compilerOptions.paths` in `tsconfig.json`, and has incomplete support for `package.json` settings. Unlike Deno, Bun does not currently support URL imports.
+{% /details %}
diff --git a/docs/runtime/nodejs.md b/docs/runtime/nodejs.md
new file mode 100644
index 000000000..a394ca3a3
--- /dev/null
+++ b/docs/runtime/nodejs.md
@@ -0,0 +1,682 @@
+Bun aims for complete Node.js API compatibility. Most `npm` packages intended for `Node.js` environments will work with Bun out of the box; the best way to know for certain is to try it.
+
+This page is updated regularly to reflect compatibility status of the latest version of Bun.
+
+## Built-in modules
+
+{% block className="ScrollFrame" %}
+{% table %}
+
+- Module
+- Status
+- Notes
+
+---
+
+- {% anchor id="node_assert" %} [`node:assert`](https://nodejs.org/api/assert.html) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_async_hooks" %} [`node:async_hooks`](https://nodejs.org/api/async_hooks.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_buffer" %} [`node:buffer`](https://nodejs.org/api/buffer.html) {% /anchor %}
+- 🟡
+- Incomplete implementation of `base64` and `base64url` encodings.
+
+---
+
+- {% anchor id="node_child_process" %} [`node:child_process`](https://nodejs.org/api/child_process.html) {% /anchor %}
+- 🟡
+- Missing IPC, `Stream` stdio, `proc.gid`, `proc.uid`, advanced serialization
+
+---
+
+- {% anchor id="node_cluster" %} [`node:cluster`](https://nodejs.org/api/cluster.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_console" %} [`node:console`](https://nodejs.org/api/console.html) {% /anchor %}
+- 🟢
+- Recommended to use `console` global instead
+
+---
+
+- {% anchor id="node_crypto" %} [`node:crypto`](https://nodejs.org/api/crypto.html) {% /anchor %}
+- 🟡
+- Missing `crypto.Certificate` `crypto.ECDH` `crypto.KeyObject` `crypto.X509Certificate` `crypto.checkPrime{Sync}` `crypto.createPrivateKey` `crypto.createPublicKey` `crypto.createSecretKey` `crypto.diffieHellman` `crypto.generateKey{Sync}` `crypto.generateKeyPair{Sync}` `crypto.generatePrime{Sync}` `crypto.getCipherInfo` `crypto.getCurves` `crypto.{get|set}Fips` `crypto.hkdf` `crypto.hkdfSync` `crypto.randomInt` `crypto.secureHeapUsed` `crypto.setEngine` `crypto.sign` `crypto.verify`
+
+---
+
+- {% anchor id="node_dgram" %} [`node:dgram`](https://nodejs.org/api/dgram.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_diagnostics_channel" %} [`node:diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_dns" %} [`node:dns`](https://nodejs.org/api/dns.html) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_domain" %} [`node:domain`](https://nodejs.org/api/domain.html) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_events" %} [`node:events`](https://nodejs.org/api/events.html) {% /anchor %}
+- 🟡
+- Missing `EventEmitterAsyncResource`. `EventEmitter` is missing `{get}set}MaxListeners` `usingDomains` `init`.
+
+---
+
+- {% anchor id="node_fs" %} [`node:fs`](https://nodejs.org/api/fs.html) {% /anchor %}
+- 🟡
+- Missing `fs.constants` `fs.fdatasync{Sync}` `fs.opendir{Sync}` `fs.readv{Sync}` `fs.{watch|watchFile|unwatchFile}` `fs.writev{Sync}`.
+
+---
+
+- {% anchor id="node_http" %} [`node:http`](https://nodejs.org/api/http.html) {% /anchor %}
+- 🟡
+- Missing `http.Agent` `http.ClientRequest` `http.IncomingMessage` `http.OutgoingMessage` `http.globalAgent` `http.get` `http.maxHeaderSize` `http.request` `http.setMaxIdleHTTPParsers` `http.validateHeader{Name|Value}`.
+
+---
+
+- {% anchor id="node_http2" %} [`node:http2`](https://nodejs.org/api/http2.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_https" %} [`node:https`](https://nodejs.org/api/https.html) {% /anchor %}
+- 🟡
+- See `node:http`.
+
+---
+
+- {% anchor id="node_inspector" %} [`node:inspector`](https://nodejs.org/api/inspector.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_module" %} [`node:module`](https://nodejs.org/api/module.html) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_net" %} [`node:net`](https://nodejs.org/api/net.html) {% /anchor %}
+- 🟡
+- Missing `net.createServer` `net.{get|set}DefaultAutoSelectFamily` `net.SocketAddress` `net.BlockList`.
+
+---
+
+- {% anchor id="node_os" %} [`node:os`](https://nodejs.org/api/os.html) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_path" %} [`node:path`](https://nodejs.org/api/path.html) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_perf_hooks" %} [`node:perf_hooks`](https://nodejs.org/api/perf_hooks.html) {% /anchor %}
+- 🟡
+- Only `perf_hooks.performance.now()` and `perf_hooks.performance.timeOrigin` are implemented. Recommended to use `performance` global instead of `perf_hooks.performance`.
+
+---
+
+- {% anchor id="node_process" %} [`node:process`](https://nodejs.org/api/process.html) {% /anchor %}
+- 🟡
+- See `Globals > process`.
+
+---
+
+- {% anchor id="node_punycode" %} [`node:punycode`](https://nodejs.org/api/punycode.html) {% /anchor %}
+- 🟢
+- Fully implemented. _Deprecated by Node.js._
+
+---
+
+- {% anchor id="node_querystring" %} [`node:querystring`](https://nodejs.org/api/querystring.html) {% /anchor %}
+- 🟡
+- Missing `querystring.escape` and `querystring.unescape`.
+
+---
+
+- {% anchor id="node_readline" %} [`node:readline`](https://nodejs.org/api/readline.html) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_repl" %} [`node:repl`](https://nodejs.org/api/repl.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_stream" %} [`node:stream`](https://nodejs.org/api/stream.html) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_string_decoder" %} [`node:string_decoder`](https://nodejs.org/api/string_decoder.html) {% /anchor %}
+- 🟢
+
+---
+
+- {% anchor id="node_sys" %} [`node:sys`](https://nodejs.org/api/util.html) {% /anchor %}
+- 🟡
+- See `node:util`.
+
+---
+
+- {% anchor id="node_timers" %} [`node:timers`](https://nodejs.org/api/timers.html) {% /anchor %}
+- 🟢
+- Recommended to use global `setTimeout`, et. al. instead.
+
+---
+
+- {% anchor id="node_tls" %} [`node:tls`](https://nodejs.org/api/tls.html) {% /anchor %}
+- 🟡
+- Missing `tls.Server` `tls.createServer` `tls.createSecurePair` `tls.checkServerIdentity` `tls.rootCertificates`
+
+---
+
+- {% anchor id="node_trace_events" %} [`node:trace_events`](https://nodejs.org/api/tracing.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_tty" %} [`node:tty`](https://nodejs.org/api/tty.html) {% /anchor %}
+- 🟡
+- Missing `tty.ReadStream` and `tty.WriteStream`.
+
+---
+
+- {% anchor id="node_url" %} [`node:url`](https://nodejs.org/api/url.html) {% /anchor %}
+- 🟡
+- Missing `url.domainTo{ASCII|Unicode}` `url.urlToHttpOptions`. Recommended to use `URL` and `URLSearchParams` globals instead.
+
+---
+
+- {% anchor id="node_util" %} [`node:util`](https://nodejs.org/api/util.html) {% /anchor %}
+- 🟡
+- Missing `util.MIMEParams` `util.MIMEType` `util.formatWithOptions()` `util.getSystemErrorMap()` `util.getSystemErrorName()` `util.parseArgs()` `util.stripVTControlCharacters()` `util.toUSVString()` `util.transferableAbortController()` `util.transferableAbortSignal()`.
+
+---
+
+- {% anchor id="node_v8" %} [`node:v8`](https://nodejs.org/api/v8.html) {% /anchor %}
+- 🔴
+- Not implemented or planned. For profiling, use `bun:jsc` instead.
+
+---
+
+- {% anchor id="node_vm" %} [`node:vm`](https://nodejs.org/api/vm.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_wasi" %} [`node:wasi`](https://nodejs.org/api/wasi.html) {% /anchor %}
+- 🟡
+- Partially implemented.
+
+---
+
+- {% anchor id="node_worker_threads" %} [`node:worker_threads`](https://nodejs.org/api/worker_threads.html) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_zlib" %} [`node:zlib`](https://nodejs.org/api/zlib.html) {% /anchor %}
+- 🟡
+- Missing `zlib.brotli*`
+
+{% /table %}
+{% /block %}
+
+## Globals
+
+The table below lists all globals implemented by Node.js and Bun's current compatibility status.
+
+{% table %}
+
+---
+
+- {% anchor id="node_abortcontroller" %} [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_abortsignal" %} [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_blob" %} [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_buffer" %} [`Buffer`](https://nodejs.org/api/buffer.html#class-buffer) {% /anchor %}
+- 🟡
+- Incomplete implementation of `base64` and `base64url` encodings.
+
+---
+
+- {% anchor id="node_bytelengthqueuingstrategy" %} [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_dirname" %} [`__dirname`](https://nodejs.org/api/globals.html#__dirname) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_filename" %} [`__filename`](https://nodejs.org/api/globals.html#__filename) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_atob" %} [`atob()`](https://developer.mozilla.org/en-US/docs/Web/API/atob) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_broadcastchannel" %} [`BroadcastChannel`](https://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_btoa" %} [`btoa()`](https://developer.mozilla.org/en-US/docs/Web/API/btoa) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_clearimmediate" %} [`clearImmediate()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearImmediate) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_clearinterval" %} [`clearInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_cleartimeout" %} [`clearTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/clearTimeout) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_compressionstream" %} [`CompressionStream`](https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_console" %} [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_countqueuingstrategy" %} [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_crypto" %} [`Crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_crypto" %} [`crypto`](https://developer.mozilla.org/en-US/docs/Web/API/crypto) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_cryptokey" %} [`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_customevent" %} [`CustomEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_decompressionstream" %} [`DecompressionStream`](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_event" %} [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_eventtarget" %} [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_exports" %} [`exports`](https://nodejs.org/api/globals.html#exports) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_fetch" %} [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_formdata" %} [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) {% /anchor %}
+- 🟢
+- Fully implemented. Added in Bun 0.7.0.
+
+---
+
+- {% anchor id="node_global" %} [`global`](https://nodejs.org/api/globals.html#global) {% /anchor %}
+- 🟢
+- Implemented. This is an object containing all objects in the global namespace. It's rarely referenced directly, as its contents are available without an additional prefix, e.g. `__dirname` instead of `global.__dirname`.
+
+---
+
+- {% anchor id="node_globalthis" %} [`globalThis`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) {% /anchor %}
+- 🟢
+- Aliases to `global`.
+
+---
+
+- {% anchor id="node_headers" %} [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_messagechannel" %} [`MessageChannel`](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_messageevent" %} [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_messageport" %} [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_module" %} [`module`](https://nodejs.org/api/globals.html#module) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_performanceentry" %} [`PerformanceEntry`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_performancemark" %} [`PerformanceMark`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMark) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_performancemeasure" %} [`PerformanceMeasure`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceMeasure) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_performanceobserver" %} [`PerformanceObserver`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_performanceobserverentrylist" %} [`PerformanceObserverEntryList`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserverEntryList) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_performanceresourcetiming" %} [`PerformanceResourceTiming`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_performance" %} [`performance`](https://developer.mozilla.org/en-US/docs/Web/API/performance) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_process" %} [`process`](https://nodejs.org/api/process.html) {% /anchor %}
+- 🟡
+- Missing `process.allowedNodeEnvironmentFlags` `process.channel()` `process.connected` `process.constrainedMemory()` `process.cpuUsage()` `process.debugPort` `process.disconnect()` `process.{get|set}ActiveResourcesInfo()` `process.{get|set}{uid|gid|egid|euid|groups}()` `process.hasUncaughtExceptionCaptureCallback` `process.initGroups()` `process.kill()` `process.listenerCount` `process.memoryUsage()` `process.report` `process.resourceUsage()` `process.setSourceMapsEnabled()` `process.send()`.
+
+---
+
+- {% anchor id="node_queuemicrotask" %} [`queueMicrotask()`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_readablebytestreamcontroller" %} [`ReadableByteStreamController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableByteStreamController) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_readablestream" %} [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_readablestreambyobreader" %} [`ReadableStreamBYOBReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBReader) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_readablestreambyobrequest" %} [`ReadableStreamBYOBRequest`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamBYOBRequest) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_readablestreamdefaultcontroller" %} [`ReadableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultController) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_readablestreamdefaultreader" %} [`ReadableStreamDefaultReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_require" %} [`require()`](https://nodejs.org/api/globals.html#require) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_response" %} [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_request" %} [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_setimmediate" %} [`setImmediate()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_setinterval" %} [`setInterval()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setInterval) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_settimeout" %} [`setTimeout()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_structuredclone" %} [`structuredClone()`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_subtlecrypto" %} [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_domexception" %} [`DOMException`](https://developer.mozilla.org/en-US/docs/Web/API/DOMException) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_textdecoder" %} [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_textdecoderstream" %} [`TextDecoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_textencoder" %} [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_textencoderstream" %} [`TextEncoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoderStream) {% /anchor %}
+- 🔴
+- Not implemented.
+
+---
+
+- {% anchor id="node_transformstream" %} [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_transformstreamdefaultcontroller" %} [`TransformStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStreamDefaultController) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_url" %} [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_urlsearchparams" %} [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_webassembly" %} [`WebAssembly`](https://nodejs.org/api/globals.html#webassembly) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_writablestream" %} [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_writablestreamdefaultcontroller" %} [`WritableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultController) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+---
+
+- {% anchor id="node_writablestreamdefaultwriter" %} [`WritableStreamDefaultWriter`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter) {% /anchor %}
+- 🟢
+- Fully implemented.
+
+{% /table %}
diff --git a/docs/runtime/plugins.md b/docs/runtime/plugins.md
new file mode 100644
index 000000000..c19ea9145
--- /dev/null
+++ b/docs/runtime/plugins.md
@@ -0,0 +1,245 @@
+{% callout %}
+**Note** — Introduced in Bun v0.1.11.
+{% /callout %}
+
+Bun's runtime can be extended to support additional file types using _plugins_. Plugins can intercept imports and perform custom loading logic: reading files, transpiling code, etc. They can be used to extend Bun's runtime with _loaders_ for additional file types.
+
+## Usage
+
+A plugin is defined as simple JavaScript object containing a `name` property and a `setup` function. Register a plugin with Bun using the `plugin` function.
+
+```tsx#yamlPlugin.ts
+import { plugin } from "bun";
+
+plugin({
+ name: "YAML loader",
+ setup(build) {
+ // implementation
+ },
+});
+```
+
+To consume this plugin, import it at the top of your project's entrypoint, before any application code is imported.
+
+```ts#app.ts
+import "./yamlPlugin.ts";
+import { config } from "./config.yml";
+
+console.log(config);
+```
+
+By convention, third-party plugins intended for consumption should export a factory function that accepts some configuration and returns a plugin object.
+
+```ts
+import { plugin } from "bun";
+import fooPlugin from "bun-plugin-foo";
+
+plugin(
+ fooPlugin({
+ // configuration
+ }),
+);
+
+// application code
+```
+
+Bun's plugin API is based on [esbuild](https://esbuild.github.io/plugins). Only a subset of the esbuild API is implemented, but some esbuild plugins "just work" in Bun, like the official [MDX loader](https://mdxjs.com/packages/esbuild/):
+
+```jsx
+import { plugin } from "bun";
+import mdx from "@mdx-js/esbuild";
+
+plugin(mdx());
+
+import { renderToStaticMarkup } from "react-dom/server";
+import Foo from "./bar.mdx";
+console.log(renderToStaticMarkup(<Foo />));
+```
+
+## Loaders
+
+<!-- The plugin logic is implemented in the `setup` function using the builder provided as the first argument (`build` in the example above). The `build` variable provides two methods: `onResolve` and `onLoad`. -->
+
+<!-- ## `onResolve` -->
+
+<!-- The `onResolve` method lets you intercept imports that match a particular regex and modify the resolution behavior, such as re-mapping the import to another file. In the simplest case, you can simply remap the matched import to a new path.
+
+```ts
+import { plugin } from "bun";
+
+plugin({
+ name: "YAML loader",
+ setup(build) {
+ build.onResolve();
+ // implementation
+ },
+});
+``` -->
+
+<!--
+Internally, Bun's transpiler automatically turns `plugin()` calls into separate files (at most 1 per file). This lets loaders activate before the rest of your application runs with zero configuration. -->
+
+Plugins are primarily used to extend Bun with loaders for additional file types. Let's look at a simple plugin that exposes envLet's look at a sample plugin that implements a loader for `.yaml` files.
+
+```ts#yamlPlugin.ts
+import { plugin } from "bun";
+
+plugin({
+ name: "YAML",
+ async setup(build) {
+ const { load } = await import("js-yaml");
+ const { readFileSync } = await import("fs");
+
+ // when a .yaml file is imported...
+ build.onLoad({ filter: /\.(yaml|yml)$/ }, (args) => {
+
+ // read and parse the file
+ const text = readFileSync(args.path, "utf8");
+ const exports = load(text) as Record<string, any>;
+
+ // and returns it as a module
+ return {
+ exports,
+ loader: "object", // special loader for JS objects
+ };
+ });
+ },
+});
+```
+
+With this plugin, data can be directly imported from `.yaml` files.
+
+{% codetabs %}
+
+```ts#index.ts
+import "./yamlPlugin.ts"
+import {name, releaseYear} from "./data.yml"
+
+console.log(name, releaseYear);
+```
+
+```yaml#data.yml
+name: Fast X
+releaseYear: 2023
+```
+
+{% /codetabs %}
+
+Note that the returned object has a `loader` property. This tells Bun which of its internal loaders should be used to handle the result. Even though we're implementing a loader for `.yaml`, the result must still be understandable by one of Bun's built-in loaders. It's loaders all the way down.
+
+In this case we're using `"object"`—a special loader (intended for use by plugins) that converts a plain JavaScript object to an equivalent ES module. Any of Bun's built-in loaders are supported; these same loaders are used by Bun internally for handling files of various extensions.
+
+{% table %}
+
+- Loader
+- Extensions
+- Output
+
+---
+
+- `js`
+- `.js` `.mjs` `.cjs`
+- Transpile to JavaScript files
+
+---
+
+- `jsx`
+- `.jsx`
+- Transform JSX then transpile
+
+---
+
+- `ts`
+- `.ts` `.mts` `cts`
+- Transform TypeScript then transpile
+
+---
+
+- `tsx`
+- `.tsx`
+- Transform TypeScript, JSX, then transpile
+
+---
+
+- `toml`
+- `.toml`
+- Parse using Bun's built-in TOML parser
+
+---
+
+- `json`
+- `.json`
+- Parse using Bun's built-in JSON parser
+
+---
+
+- `object`
+- —
+- A special loader intended for plugins that converts a plain JavaScript object to an equivalent ES module. Each key in the object corresponds to a named export.
+
+{% /callout %}
+
+Loading a YAML file is useful, but plugins support more than just data loading. Lets look at a plugin that lets Bun import `*.svelte` files.
+
+```ts#sveltePlugin.ts
+import { plugin } from "bun";
+
+await plugin({
+ name: "svelte loader",
+ async setup(build) {
+ const { compile } = await import("svelte/compiler");
+ const { readFileSync } = await import("fs");
+
+ // when a .svelte file is imported...
+ build.onLoad({ filter: /\.svelte$/ }, ({ path }) => {
+
+ // read and compile it with the Svelte compiler
+ const file = readFileSync(path, "utf8");
+ const contents = compile(file, {
+ filename: path,
+ generate: "ssr",
+ }).js.code;
+
+ // and return the compiled source code as "js"
+ return {
+ contents,
+ loader: "js",
+ };
+ });
+ },
+});
+```
+
+> Note: in a production implementation, you'd want to cache the compiled output and include additional error handling.
+
+The object returned from `build.onLoad` contains the compiled source code in `contents` and specifies `"js"` as its loader. That tells Bun to consider the returned `contents` to be a JavaScript module and transpile it using Bun's built-in `js` loader.
+
+With this plugin, Svelte components can now be directly imported and consumed.
+
+```js
+import "./sveltePlugin.ts";
+import MySvelteComponent from "./component.svelte";
+
+console.log(mySvelteComponent.render());
+```
+
+## Reference
+
+```ts
+namespace Bun {
+ function plugin(plugin: { name: string; setup: (build: PluginBuilder) => void }): void;
+}
+
+type PluginBuilder = {
+ onLoad: (
+ args: { filter: RegExp; namespace?: string },
+ callback: (args: { path: string }) => {
+ loader?: "js" | "jsx" | "ts" | "tsx" | "json" | "yaml" | "object";
+ contents?: string;
+ exports?: Record<string, any>;
+ },
+ ) => void;
+};
+```
+
+The `onLoad` method optionally accepts a `namespace` in addition to the `filter` regex. This namespace will be be used to prefix the import in transpiled code; for instance, a loader with a `filter: /\.yaml$/` and `namespace: "yaml:"` will transform an import from `./myfile.yaml` into `yaml:./myfile.yaml`.
diff --git a/docs/runtime/streams.md b/docs/runtime/streams.md
deleted file mode 100644
index 733b99799..000000000
--- a/docs/runtime/streams.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Streams in Bun
-
-Bun supports Web Streams ([`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) and [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) first and partially supports Node.js [`"stream"`](https://nodejs.org/api/stream.html).
-
-## `ReadableStream`
diff --git a/docs/runtime/web-apis.md b/docs/runtime/web-apis.md
new file mode 100644
index 000000000..ebe0e6041
--- /dev/null
+++ b/docs/runtime/web-apis.md
@@ -0,0 +1,300 @@
+Many web APIs aren't relevant in the context of a server-first runtime like Bun, such as the [DOM API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API#html_dom_api_interfaces), [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), and [`History`](https://developer.mozilla.org/en-US/docs/Web/API/History_API). Many others, though, are broadly useful outside of the browser context; when possible, Bun implements these Web-standard APIs instead of introducing new APIs.
+
+The following Web APIs are partially or completely supported.
+
+## Globals
+
+{% table %}
+
+---
+
+- Crypto
+- [`crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)
+ [`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)
+
+---
+
+- Debugging
+
+- [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)[`performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance)
+
+---
+
+- Encoding and decoding
+- [`atob`](https://developer.mozilla.org/en-US/docs/Web/API/atob) [`btoa`](https://developer.mozilla.org/en-US/docs/Web/API/btoa) [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder)
+
+---
+
+- Timeouts
+- [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout)
+
+---
+
+- Intervals
+- [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval)[`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval)
+
+---
+
+- HTTP
+- [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
+
+---
+
+- Microtasks
+- [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
+
+---
+
+- Errors
+- [`reportError`](https://developer.mozilla.org/en-US/docs/Web/API/reportError) [`ResolveError`](https://developer.mozilla.org/en-US/docs/Web/API/ResolveError)
+ [`BuildError`](https://developer.mozilla.org/en-US/docs/Web/API/BuildError)
+
+---
+
+- User interaction
+- [`alert`](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert) [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) [`prompt`](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt)
+
+<!-- - Blocking. Prints the alert message to terminal and awaits `[ENTER]` before proceeding. -->
+<!-- - Blocking. Prints confirmation message and awaits `[y/N]` input from user. Returns `true` if user entered `y` or `Y`, `false` otherwise.
+- Blocking. Prints prompt message and awaits user input. Returns the user input as a string. -->
+
+- Blob
+- [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
+
+---
+
+- Realms
+- [`ShadowRealm`](https://github.com/tc39/proposal-shadowrealm)
+
+---
+
+- Events
+- [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget)
+ [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event) [`ErrorEvent`](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent) [`CloseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent) [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent)
+
+---
+
+- WebSockets
+- [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
+
+---
+
+- URLs
+- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
+
+---
+
+- Streams
+- [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream) [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy) [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy) plus associated `*Reader`, `*Writer`, and `*Controller` classes.
+
+<!-- ## Globals
+
+{% table %}
+
+---
+
+---
+
+- [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)
+
+---
+
+- [`crypto`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto)
+
+---
+
+- [`performance`](https://developer.mozilla.org/en-US/docs/Web/API/Performance)
+
+{% /table %}
+
+## Functions
+
+{% table %}
+
+- [`atob`](https://developer.mozilla.org/en-US/docs/Web/API/atob)
+
+---
+
+- [`btoa`](https://developer.mozilla.org/en-US/docs/Web/API/btoa)
+
+---
+
+- [`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval)
+
+---
+
+- [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout)
+
+---
+
+- [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/fetch)
+
+---
+
+- [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
+
+---
+
+- [`reportError`](https://developer.mozilla.org/en-US/docs/Web/API/reportError)
+
+---
+
+- [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval)
+
+---
+
+- [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout)
+
+---
+
+- [`alert`](https://developer.mozilla.org/en-US/docs/Web/API/alert)
+- Blocking. Prints the alert message to terminal and awaits `[ENTER]` before proceeding.
+
+---
+
+- [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/confirm)
+- Blocking. Prints confirmation message and awaits `[y/N]` input from user. Returns `true` if user entered `y` or `Y`, `false` otherwise.
+
+---
+
+- [`prompt`](https://developer.mozilla.org/en-US/docs/Web/API/prompt)
+- Blocking. Prints prompt message and awaits user input. Returns the user input as a string.
+
+---
+
+- [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)
+
+{% /table %}
+
+## Classes
+
+{% table %}
+
+---
+
+- [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
+
+---
+
+- [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)
+
+---
+
+- [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request)
+
+---
+
+- [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) and [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder)
+
+---
+
+---
+
+- [`ShadowRealm`](https://github.com/tc39/proposal-shadowrealm)
+- A ["better `eval`](https://2ality.com/2022/04/shadow-realms.html). Currently a Stage 3 TC39 proposal
+
+---
+
+- [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
+
+---
+
+- [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget)
+
+---
+
+- [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event)
+
+---
+
+- [`ErrorEvent`](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent)
+
+---
+
+- [`CloseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent)
+
+---
+
+- [`MessageEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent)
+
+---
+
+- [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
+
+---
+
+- [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
+
+---
+
+- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL)
+
+---
+
+- [`AbortController`](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
+
+---
+
+- [`Loader`](https://developer.mozilla.org/en-US/docs/Web/API/Loader)
+
+---
+
+- [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)
+
+---
+
+- [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)
+
+---
+
+- [`ByteLengthQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/ByteLengthQueuingStrategy)
+
+---
+
+- [`ReadableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultController)
+
+---
+
+- [`ReadableStreamDefaultReader`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader)
+
+---
+
+- [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStream)
+
+---
+
+- [`WritableStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultController)
+
+---
+
+- [`WritableStreamDefaultWriter`](https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter)
+
+---
+
+- [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream)
+
+---
+
+- [`TransformStreamDefaultController`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStreamDefaultController)
+
+---
+
+- [`CountQueuingStrategy`](https://developer.mozilla.org/en-US/docs/Web/API/CountQueuingStrategy)
+
+---
+
+- [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)
+
+---
+
+- [`CryptoKey`](https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey)
+
+---
+
+- [`ResolveError`](https://developer.mozilla.org/en-US/docs/Web/API/ResolveError)
+
+---
+
+- [`BuildError`](https://developer.mozilla.org/en-US/docs/Web/API/BuildError)
+
+{% /table %} -->