mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
## Summary Updates documentation for all major features and changes introduced in Bun v1.3.2 blog post. ## Changes ### Package Manager - ✅ Document `configVersion` system for controlling default linker behavior - ✅ Clarify that "existing projects (made pre-v1.3.2)" use hoisted installs for backward compatibility - ✅ Add smart postinstall script optimization with environment variable flags - ✅ Document improved Git dependency resolution with HTTP tarball optimization - ✅ Add `bun list` alias for `bun pm ls` ### Testing - ✅ Document new `onTestFinished` lifecycle hook with simple example - ✅ Add to lifecycle hooks table in test documentation ### Runtime & Performance - ✅ Add CPU profiling with `--cpu-prof` flag documentation - ✅ Place after memory usage section for better flow ### WebSockets - ✅ Add `subscriptions` getter to existing pub/sub example - ✅ Add TypeScript reference for the subscriptions property ## Documentation Improvements All documentation now consistently: - Uses "made pre-v1.3.2" to clarify existing project behavior - Simplifies default linker explanations with clear references to `/docs/pm/isolated-installs` - Uses `/docs/pm/isolated-installs` for all internal references - Avoids confusing technical details in favor of user-friendly summaries ## Files Modified - `docs/guides/install/add-git.mdx` - Added GitHub tarball optimization note - `docs/pm/cli/install.mdx` - Added installation strategies and smart postinstall docs - `docs/pm/cli/pm.mdx` - Added bun list alias - `docs/pm/isolated-installs.mdx` - Updated default behavior section with configVersion table - `docs/project/benchmarking.mdx` - Added CPU profiling section - `docs/runtime/bunfig.mdx` - Clarified install.linker defaults - `docs/runtime/http/websockets.mdx` - Added subscriptions to example and TypeScript interface - `docs/test/lifecycle.mdx` - Added onTestFinished hook documentation ## Diff ````diff diff --git a/docs/guides/install/add-git.mdx b/docs/guides/install/add-git.mdx index 70950e1a63..7f8f3c8d81 100644 --- a/docs/guides/install/add-git.mdx +++ b/docs/guides/install/add-git.mdx @@ -33,6 +33,8 @@ bun add git@github.com:lodash/lodash.git bun add github:colinhacks/zod ``` +**Note:** GitHub dependencies download via HTTP tarball when possible for faster installation. + --- See [Docs > Package manager](https://bun.com/docs/cli/install) for complete documentation of Bun's package manager. diff --git a/docs/pm/cli/install.mdx b/docs/pm/cli/install.mdx index 7affb62646..dde268b7e5 100644 --- a/docs/pm/cli/install.mdx +++ b/docs/pm/cli/install.mdx @@ -88,6 +88,13 @@ Lifecycle scripts will run in parallel during installation. To adjust the maximu bun install --concurrent-scripts 5 ``` +Bun automatically optimizes postinstall scripts for popular packages (like `esbuild`, `sharp`, etc.) by determining which scripts need to run. To disable these optimizations: + +```bash terminal icon="terminal" +BUN_FEATURE_FLAG_DISABLE_NATIVE_DEPENDENCY_LINKER=1 bun install +BUN_FEATURE_FLAG_DISABLE_IGNORE_SCRIPTS=1 bun install +``` + --- ## Workspaces @@ -231,7 +238,7 @@ Bun supports installing dependencies from Git, GitHub, and local or remotely-hos Bun supports two package installation strategies that determine how dependencies are organized in `node_modules`: -### Hoisted installs (default for single projects) +### Hoisted installs The traditional npm/Yarn approach that flattens dependencies into a shared `node_modules` directory: @@ -249,7 +256,15 @@ bun install --linker isolated Isolated installs create a central package store in `node_modules/.bun/` with symlinks in the top-level `node_modules`. This ensures packages can only access their declared dependencies. -For complete documentation on isolated installs, refer to [Package manager > Isolated installs](/pm/isolated-installs). +### Default strategy + +The default linker strategy depends on whether you're starting fresh or have an existing project: + +- **New workspaces/monorepos**: `isolated` (prevents phantom dependencies) +- **New single-package projects**: `hoisted` (traditional npm behavior) +- **Existing projects (made pre-v1.3.2)**: `hoisted` (preserves backward compatibility) + +The default is controlled by a `configVersion` field in your lockfile. For a detailed explanation, see [Package manager > Isolated installs](/docs/pm/isolated-installs). --- @@ -319,8 +334,7 @@ dryRun = false concurrentScripts = 16 # (cpu count or GOMAXPROCS) x2 # installation strategy: "hoisted" or "isolated" -# default: "hoisted" (for single-project projects) -# default: "isolated" (for monorepo projects) +# default varies by project type - see /docs/pm/isolated-installs linker = "hoisted" diff --git a/docs/pm/cli/pm.mdx b/docs/pm/cli/pm.mdx index fc297753d3..9c8faa7da1 100644 --- a/docs/pm/cli/pm.mdx +++ b/docs/pm/cli/pm.mdx @@ -115,6 +115,8 @@ To print a list of installed dependencies in the current project and their resol ```bash terminal icon="terminal" bun pm ls +# or +bun list ``` ```txt @@ -130,6 +132,8 @@ To print all installed dependencies, including nth-order dependencies. ```bash terminal icon="terminal" bun pm ls --all +# or +bun list --all ``` ```txt diff --git a/docs/pm/isolated-installs.mdx b/docs/pm/isolated-installs.mdx index 73c6748b15..17afe02fe1 100644 --- a/docs/pm/isolated-installs.mdx +++ b/docs/pm/isolated-installs.mdx @@ -5,7 +5,7 @@ description: "Strict dependency isolation similar to pnpm's approach" Bun provides an alternative package installation strategy called **isolated installs** that creates strict dependency isolation similar to pnpm's approach. This mode prevents phantom dependencies and ensures reproducible, deterministic builds. -This is the default installation strategy for monorepo projects. +This is the default installation strategy for **new** workspace/monorepo projects (with `configVersion = 1` in the lockfile). Existing projects continue using hoisted installs unless explicitly configured. ## What are isolated installs? @@ -43,8 +43,23 @@ linker = "isolated" ### Default behavior -- For monorepo projects, Bun uses the **isolated** installation strategy by default. -- For single-project projects, Bun uses the **hoisted** installation strategy by default. +The default linker strategy depends on your project's lockfile `configVersion`: + +| `configVersion` | Using workspaces? | Default Linker | +| --------------- | ----------------- | -------------- | +| `1` | ✅ | `isolated` | +| `1` | ❌ | `hoisted` | +| `0` | ✅ | `hoisted` | +| `0` | ❌ | `hoisted` | + +**New projects**: Default to `configVersion = 1`. In workspaces, v1 uses the isolated linker by default; otherwise it uses hoisted linking. + +**Existing Bun projects (made pre-v1.3.2)**: If your existing lockfile doesn't have a version yet, Bun sets `configVersion = 0` when you run `bun install`, preserving the previous hoisted linker default. + +**Migrations from other package managers**: + +- From pnpm: `configVersion = 1` (using isolated installs in workspaces) +- From npm or yarn: `configVersion = 0` (using hoisted installs) You can override the default behavior by explicitly specifying the `--linker` flag or setting it in your configuration file. diff --git a/docs/project/benchmarking.mdx b/docs/project/benchmarking.mdx index 1263a06729..2ab8bcafc8 100644 --- a/docs/project/benchmarking.mdx +++ b/docs/project/benchmarking.mdx @@ -216,3 +216,26 @@ numa nodes: 1 elapsed: 0.068 s process: user: 0.061 s, system: 0.014 s, faults: 0, rss: 57.4 MiB, commit: 64.0 MiB ``` + +## CPU profiling + +Profile JavaScript execution to identify performance bottlenecks with the `--cpu-prof` flag. + +```sh terminal icon="terminal" +bun --cpu-prof script.js +``` + +This generates a `.cpuprofile` file you can open in Chrome DevTools (Performance tab → Load profile) or VS Code's CPU profiler. + +### Options + +```sh terminal icon="terminal" +bun --cpu-prof --cpu-prof-name my-profile.cpuprofile script.js +bun --cpu-prof --cpu-prof-dir ./profiles script.js +``` + +| Flag | Description | +| ---------------------------- | -------------------- | +| `--cpu-prof` | Enable profiling | +| `--cpu-prof-name <filename>` | Set output filename | +| `--cpu-prof-dir <dir>` | Set output directory | diff --git a/docs/runtime/bunfig.mdx b/docs/runtime/bunfig.mdx index 91005c1607..5b7fe49823 100644 --- a/docs/runtime/bunfig.mdx +++ b/docs/runtime/bunfig.mdx @@ -497,9 +497,9 @@ print = "yarn" ### `install.linker` -Configure the default linker strategy. Default `"hoisted"` for single-project projects, `"isolated"` for monorepo projects. +Configure the linker strategy for installing dependencies. Defaults to `"isolated"` for new workspaces, `"hoisted"` for new single-package projects and existing projects (made pre-v1.3.2). -For complete documentation refer to [Package manager > Isolated installs](/pm/isolated-installs). +For complete documentation refer to [Package manager > Isolated installs](/docs/pm/isolated-installs). ```toml title="bunfig.toml" icon="settings" [install] diff --git a/docs/runtime/http/websockets.mdx b/docs/runtime/http/websockets.mdx index b33f37c29f..174043200d 100644 --- a/docs/runtime/http/websockets.mdx +++ b/docs/runtime/http/websockets.mdx @@ -212,6 +212,9 @@ const server = Bun.serve({ // this is a group chat // so the server re-broadcasts incoming message to everyone server.publish("the-group-chat", `${ws.data.username}: ${message}`); + + // inspect current subscriptions + console.log(ws.subscriptions); // ["the-group-chat"] }, close(ws) { const msg = `${ws.data.username} has left the chat`; @@ -393,6 +396,7 @@ interface ServerWebSocket { readonly data: any; readonly readyState: number; readonly remoteAddress: string; + readonly subscriptions: string[]; send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number; close(code?: number, reason?: string): void; subscribe(topic: string): void; diff --git a/docs/test/lifecycle.mdx b/docs/test/lifecycle.mdx index 6427175df6..3837f0e948 100644 --- a/docs/test/lifecycle.mdx +++ b/docs/test/lifecycle.mdx @@ -6,11 +6,12 @@ description: "Learn how to use beforeAll, beforeEach, afterEach, and afterAll li The test runner supports the following lifecycle hooks. This is useful for loading test fixtures, mocking data, and configuring the test environment. | Hook | Description | -| ------------ | --------------------------- | +| ---------------- | ---------------------------------------------------------- | | `beforeAll` | Runs once before all tests. | | `beforeEach` | Runs before each test. | | `afterEach` | Runs after each test. | | `afterAll` | Runs once after all tests. | +| `onTestFinished` | Runs after a single test finishes (after all `afterEach`). | ## Per-Test Setup and Teardown @@ -90,6 +91,23 @@ describe("test group", () => { }); ``` +### `onTestFinished` + +Use `onTestFinished` to run a callback after a single test completes. It runs after all `afterEach` hooks. + +```ts title="test.ts" icon="/icons/typescript.svg" +import { test, onTestFinished } from "bun:test"; + +test("cleanup after test", () => { + onTestFinished(() => { + // runs after all afterEach hooks + console.log("test finished"); + }); +}); +``` + +Not supported in concurrent tests; use `test.serial` instead. + ## Global Setup and Teardown To scope the hooks to an entire multi-file test run, define the hooks in a separate file. ```` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Michael H <git@riskymh.dev> Co-authored-by: Lydia Hallie <lydiajuliettehallie@gmail.com>
409 lines
13 KiB
Plaintext
409 lines
13 KiB
Plaintext
---
|
|
title: WebSockets
|
|
description: Server-side WebSockets in Bun
|
|
---
|
|
|
|
`Bun.serve()` supports server-side WebSockets, with on-the-fly compression, TLS support, and a Bun-native publish-subscribe API.
|
|
|
|
<Info>
|
|
|
|
**⚡️ 7x more throughput**
|
|
|
|
Bun's WebSockets are fast. For a [simple chatroom](https://github.com/oven-sh/bun/tree/main/bench/websocket-server/README.md) on Linux x64, Bun can handle 7x more requests per second than Node.js + [`"ws"`](https://github.com/websockets/ws).
|
|
|
|
| **Messages sent per second** | **Runtime** | **Clients** |
|
|
| ---------------------------- | ------------------------------ | ----------- |
|
|
| ~700,000 | (`Bun.serve`) Bun v0.2.1 (x64) | 16 |
|
|
| ~100,000 | (`ws`) Node v18.10.0 (x64) | 16 |
|
|
|
|
Internally Bun's WebSocket implementation is built on [uWebSockets](https://github.com/uNetworking/uWebSockets).
|
|
|
|
</Info>
|
|
|
|
---
|
|
|
|
## Start a WebSocket server
|
|
|
|
Below is a simple WebSocket server built with `Bun.serve`, in which all incoming requests are [upgraded](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) to WebSocket connections in the `fetch` handler. The socket handlers are declared in the `websocket` parameter.
|
|
|
|
```ts server.ts icon="/icons/typescript.svg"
|
|
Bun.serve({
|
|
fetch(req, server) {
|
|
// upgrade the request to a WebSocket
|
|
if (server.upgrade(req)) {
|
|
return; // do not return a Response
|
|
}
|
|
return new Response("Upgrade failed", { status: 500 });
|
|
},
|
|
websocket: {}, // handlers
|
|
});
|
|
```
|
|
|
|
The following WebSocket event handlers are supported:
|
|
|
|
```ts server.ts icon="/icons/typescript.svg"
|
|
Bun.serve({
|
|
fetch(req, server) {}, // upgrade logic
|
|
websocket: {
|
|
message(ws, message) {}, // a message is received
|
|
open(ws) {}, // a socket is opened
|
|
close(ws, code, message) {}, // a socket is closed
|
|
drain(ws) {}, // the socket is ready to receive more data
|
|
},
|
|
});
|
|
```
|
|
|
|
<Accordion title="An API designed for speed">
|
|
|
|
In Bun, handlers are declared once per server, instead of per socket.
|
|
|
|
`ServerWebSocket` expects you to pass a `WebSocketHandler` object to the `Bun.serve()` method which has methods for `open`, `message`, `close`, `drain`, and `error`. This is different than the client-side `WebSocket` class which extends `EventTarget` (onmessage, onopen, onclose),
|
|
|
|
Clients tend to not have many socket connections open so an event-based API makes sense.
|
|
|
|
But servers tend to have **many** socket connections open, which means:
|
|
|
|
- Time spent adding/removing event listeners for each connection adds up
|
|
- Extra memory spent on storing references to callbacks function for each connection
|
|
- Usually, people create new functions for each connection, which also means more memory
|
|
|
|
So, instead of using an event-based API, `ServerWebSocket` expects you to pass a single object with methods for each event in `Bun.serve()` and it is reused for each connection.
|
|
|
|
This leads to less memory usage and less time spent adding/removing event listeners.
|
|
|
|
</Accordion>
|
|
|
|
The first argument to each handler is the instance of `ServerWebSocket` handling the event. The `ServerWebSocket` class is a fast, Bun-native implementation of [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) with some additional features.
|
|
|
|
```ts server.ts icon="/icons/typescript.svg"
|
|
Bun.serve({
|
|
fetch(req, server) {}, // upgrade logic
|
|
websocket: {
|
|
message(ws, message) {
|
|
ws.send(message); // echo back the message
|
|
},
|
|
},
|
|
});
|
|
```
|
|
|
|
### Sending messages
|
|
|
|
Each `ServerWebSocket` instance has a `.send()` method for sending messages to the client. It supports a range of input types.
|
|
|
|
```ts server.ts icon="/icons/typescript.svg" focus={4-6}
|
|
Bun.serve({
|
|
fetch(req, server) {}, // upgrade logic
|
|
websocket: {
|
|
message(ws, message) {
|
|
ws.send("Hello world"); // string
|
|
ws.send(response.arrayBuffer()); // ArrayBuffer
|
|
ws.send(new Uint8Array([1, 2, 3])); // TypedArray | DataView
|
|
},
|
|
},
|
|
});
|
|
```
|
|
|
|
### Headers
|
|
|
|
Once the upgrade succeeds, Bun will send a `101 Switching Protocols` response per the [spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism). Additional `headers` can be attached to this `Response` in the call to `server.upgrade()`.
|
|
|
|
```ts server.ts icon="/icons/typescript.svg"
|
|
Bun.serve({
|
|
fetch(req, server) {
|
|
const sessionId = await generateSessionId();
|
|
server.upgrade(req, {
|
|
headers: {
|
|
// [!code ++]
|
|
"Set-Cookie": `SessionId=${sessionId}`, // [!code ++]
|
|
}, // [!code ++]
|
|
});
|
|
},
|
|
websocket: {}, // handlers
|
|
});
|
|
```
|
|
|
|
### Contextual data
|
|
|
|
Contextual `data` can be attached to a new WebSocket in the `.upgrade()` call. This data is made available on the `ws.data` property inside the WebSocket handlers.
|
|
|
|
```ts server.ts icon="/icons/typescript.svg"
|
|
type WebSocketData = {
|
|
createdAt: number;
|
|
channelId: string;
|
|
authToken: string;
|
|
};
|
|
|
|
Bun.serve({
|
|
fetch(req, server) {
|
|
const cookies = new Bun.CookieMap(req.headers.get("cookie")!);
|
|
|
|
server.upgrade(req, {
|
|
// this object must conform to WebSocketData
|
|
data: {
|
|
createdAt: Date.now(),
|
|
channelId: new URL(req.url).searchParams.get("channelId"),
|
|
authToken: cookies.get("X-Token"),
|
|
},
|
|
});
|
|
|
|
return undefined;
|
|
},
|
|
websocket: {
|
|
// TypeScript: specify the type of ws.data like this
|
|
data: {} as WebSocketData,
|
|
// handler called when a message is received
|
|
async message(ws, message) {
|
|
// ws.data is now properly typed as WebSocketData
|
|
const user = getUserFromToken(ws.data.authToken);
|
|
|
|
await saveMessageToDatabase({
|
|
channel: ws.data.channelId,
|
|
message: String(message),
|
|
userId: user.id,
|
|
});
|
|
},
|
|
},
|
|
});
|
|
```
|
|
|
|
To connect to this server from the browser, create a new `WebSocket`.
|
|
|
|
```ts browser.js icon="file-code"
|
|
const socket = new WebSocket("ws://localhost:3000/chat");
|
|
|
|
socket.addEventListener("message", event => {
|
|
console.log(event.data);
|
|
});
|
|
```
|
|
|
|
<Info>
|
|
**Identifying users**
|
|
|
|
The cookies that are currently set on the page will be sent with the WebSocket upgrade request and available on `req.headers` in the `fetch` handler. Parse these cookies to determine the identity of the connecting user and set the value of `data` accordingly.
|
|
|
|
</Info>
|
|
|
|
### Pub/Sub
|
|
|
|
Bun's `ServerWebSocket` implementation implements a native publish-subscribe API for topic-based broadcasting. Individual sockets can `.subscribe()` to a topic (specified with a string identifier) and `.publish()` messages to all other subscribers to that topic (excluding itself). This topic-based broadcast API is similar to [MQTT](https://en.wikipedia.org/wiki/MQTT) and [Redis Pub/Sub](https://redis.io/topics/pubsub).
|
|
|
|
```ts server.ts icon="/icons/typescript.svg"
|
|
const server = Bun.serve({
|
|
fetch(req, server) {
|
|
const url = new URL(req.url);
|
|
if (url.pathname === "/chat") {
|
|
console.log(`upgrade!`);
|
|
const username = getUsernameFromReq(req);
|
|
const success = server.upgrade(req, { data: { username } });
|
|
return success ? undefined : new Response("WebSocket upgrade error", { status: 400 });
|
|
}
|
|
|
|
return new Response("Hello world");
|
|
},
|
|
websocket: {
|
|
// TypeScript: specify the type of ws.data like this
|
|
data: {} as { username: string },
|
|
open(ws) {
|
|
const msg = `${ws.data.username} has entered the chat`;
|
|
ws.subscribe("the-group-chat");
|
|
server.publish("the-group-chat", msg);
|
|
},
|
|
message(ws, message) {
|
|
// this is a group chat
|
|
// so the server re-broadcasts incoming message to everyone
|
|
server.publish("the-group-chat", `${ws.data.username}: ${message}`);
|
|
|
|
// inspect current subscriptions
|
|
console.log(ws.subscriptions); // ["the-group-chat"]
|
|
},
|
|
close(ws) {
|
|
const msg = `${ws.data.username} has left the chat`;
|
|
ws.unsubscribe("the-group-chat");
|
|
server.publish("the-group-chat", msg);
|
|
},
|
|
},
|
|
});
|
|
|
|
console.log(`Listening on ${server.hostname}:${server.port}`);
|
|
```
|
|
|
|
Calling `.publish(data)` will send the message to all subscribers of a topic _except_ the socket that called `.publish()`. To send a message to all subscribers of a topic, use the `.publish()` method on the `Server` instance.
|
|
|
|
```ts
|
|
const server = Bun.serve({
|
|
websocket: {
|
|
// ...
|
|
},
|
|
});
|
|
|
|
// listen for some external event
|
|
server.publish("the-group-chat", "Hello world");
|
|
```
|
|
|
|
### Compression
|
|
|
|
Per-message [compression](https://websockets.readthedocs.io/en/stable/topics/compression.html) can be enabled with the `perMessageDeflate` parameter.
|
|
|
|
```ts server.ts icon="/icons/typescript.svg"
|
|
Bun.serve({
|
|
websocket: {
|
|
perMessageDeflate: true, // [!code ++]
|
|
},
|
|
});
|
|
```
|
|
|
|
Compression can be enabled for individual messages by passing a `boolean` as the second argument to `.send()`.
|
|
|
|
```ts
|
|
ws.send("Hello world", true);
|
|
```
|
|
|
|
For fine-grained control over compression characteristics, refer to the [Reference](#reference).
|
|
|
|
### Backpressure
|
|
|
|
The `.send(message)` method of `ServerWebSocket` returns a `number` indicating the result of the operation.
|
|
|
|
- `-1` — The message was enqueued but there is backpressure
|
|
- `0` — The message was dropped due to a connection issue
|
|
- `1+` — The number of bytes sent
|
|
|
|
This gives you better control over backpressure in your server.
|
|
|
|
### Timeouts and limits
|
|
|
|
By default, Bun will close a WebSocket connection if it is idle for 120 seconds. This can be configured with the `idleTimeout` parameter.
|
|
|
|
```ts
|
|
Bun.serve({
|
|
fetch(req, server) {}, // upgrade logic
|
|
websocket: {
|
|
idleTimeout: 60, // 60 seconds // [!code ++]
|
|
},
|
|
});
|
|
```
|
|
|
|
Bun will also close a WebSocket connection if it receives a message that is larger than 16 MB. This can be configured with the `maxPayloadLength` parameter.
|
|
|
|
```ts
|
|
Bun.serve({
|
|
fetch(req, server) {}, // upgrade logic
|
|
websocket: {
|
|
maxPayloadLength: 1024 * 1024, // 1 MB // [!code ++]
|
|
},
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## Connect to a `Websocket` server
|
|
|
|
Bun implements the `WebSocket` class. To create a WebSocket client that connects to a `ws://` or `wss://` server, create an instance of `WebSocket`, as you would in the browser.
|
|
|
|
```ts
|
|
const socket = new WebSocket("ws://localhost:3000");
|
|
|
|
// With subprotocol negotiation
|
|
const socket2 = new WebSocket("ws://localhost:3000", ["soap", "wamp"]);
|
|
```
|
|
|
|
In browsers, the cookies that are currently set on the page will be sent with the WebSocket upgrade request. This is a standard feature of the `WebSocket` API.
|
|
|
|
For convenience, Bun lets you setting custom headers directly in the constructor. This is a Bun-specific extension of the `WebSocket` standard. _This will not work in browsers._
|
|
|
|
```ts
|
|
const socket = new WebSocket("ws://localhost:3000", {
|
|
headers: {
|
|
/* custom headers */
|
|
}, // [!code ++]
|
|
});
|
|
```
|
|
|
|
To add event listeners to the socket:
|
|
|
|
```ts
|
|
// message is received
|
|
socket.addEventListener("message", event => {});
|
|
|
|
// socket opened
|
|
socket.addEventListener("open", event => {});
|
|
|
|
// socket closed
|
|
socket.addEventListener("close", event => {});
|
|
|
|
// error handler
|
|
socket.addEventListener("error", event => {});
|
|
```
|
|
|
|
---
|
|
|
|
## Reference
|
|
|
|
```ts See Typescript Definitions expandable
|
|
namespace Bun {
|
|
export function serve(params: {
|
|
fetch: (req: Request, server: Server) => Response | Promise<Response>;
|
|
websocket?: {
|
|
message: (ws: ServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
|
|
open?: (ws: ServerWebSocket) => void;
|
|
close?: (ws: ServerWebSocket, code: number, reason: string) => void;
|
|
error?: (ws: ServerWebSocket, error: Error) => void;
|
|
drain?: (ws: ServerWebSocket) => void;
|
|
|
|
maxPayloadLength?: number; // default: 16 * 1024 * 1024 = 16 MB
|
|
idleTimeout?: number; // default: 120 (seconds)
|
|
backpressureLimit?: number; // default: 1024 * 1024 = 1 MB
|
|
closeOnBackpressureLimit?: boolean; // default: false
|
|
sendPings?: boolean; // default: true
|
|
publishToSelf?: boolean; // default: false
|
|
|
|
perMessageDeflate?:
|
|
| boolean
|
|
| {
|
|
compress?: boolean | Compressor;
|
|
decompress?: boolean | Compressor;
|
|
};
|
|
};
|
|
}): Server;
|
|
}
|
|
|
|
type Compressor =
|
|
| `"disable"`
|
|
| `"shared"`
|
|
| `"dedicated"`
|
|
| `"3KB"`
|
|
| `"4KB"`
|
|
| `"8KB"`
|
|
| `"16KB"`
|
|
| `"32KB"`
|
|
| `"64KB"`
|
|
| `"128KB"`
|
|
| `"256KB"`;
|
|
|
|
interface Server {
|
|
pendingWebSockets: number;
|
|
publish(topic: string, data: string | ArrayBufferView | ArrayBuffer, compress?: boolean): number;
|
|
upgrade(
|
|
req: Request,
|
|
options?: {
|
|
headers?: HeadersInit;
|
|
data?: any;
|
|
},
|
|
): boolean;
|
|
}
|
|
|
|
interface ServerWebSocket {
|
|
readonly data: any;
|
|
readonly readyState: number;
|
|
readonly remoteAddress: string;
|
|
readonly subscriptions: string[];
|
|
send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
|
|
close(code?: number, reason?: string): void;
|
|
subscribe(topic: string): void;
|
|
unsubscribe(topic: string): void;
|
|
publish(topic: string, message: string | ArrayBuffer | Uint8Array): void;
|
|
isSubscribed(topic: string): boolean;
|
|
cork(cb: (ws: ServerWebSocket) => void): void;
|
|
}
|
|
```
|