Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .changeset/standalone-compile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
"wrangler": minor
"miniflare": minor
"@cloudflare/vite-plugin": minor
---

Add an experimental `wrangler compile` command (and Vite `standalone` mode) for self-hosting Workers on standalone `workerd`

`wrangler compile` builds your Worker into a self-contained `workerd` bundle (a `config.capnp`, embedded modules, on-disk static assets, a version-pinned `Dockerfile`, an entrypoint, and a `README.md` with run instructions) that you can run on any server outside of Cloudflare. Static assets are wired up out of the box. Pass `--serve` to run the emitted bundle locally with the bundled `workerd` binary — the exact artifact that ships. Pass `--format binary` to emit a single self-contained `config.bin` instead of the human-readable `config.capnp` plus embedded module files.

You can also set `"standalone": true` in your configuration (or pass `--standalone` to `wrangler dev`) to opt in. When set, `wrangler dev` warns about bindings that work locally but are not yet supported by standalone `workerd`, and `wrangler deploy` errors (since the Worker targets a self-hosted runtime rather than Cloudflare).

For Vite projects, pass `standalone: true` to the `cloudflare()` plugin and `vite build` will also emit the same standalone bundle:

```ts
// vite.config.ts
import { cloudflare } from "@cloudflare/vite-plugin";
import { defineConfig } from "vite";

export default defineConfig({
plugins: [cloudflare({ standalone: true })],
});
```

```jsonc
// wrangler.json
{
"name": "my-worker",
"main": "src/index.js",
"compatibility_date": "2025-05-01",
"standalone": true,
"assets": { "directory": "./public", "binding": "ASSETS" },
}
```

This is experimental and currently targets stateless Workers plus static assets; stateful bindings (KV, R2, D1, Durable Objects, etc.) are not yet supported.
554 changes: 554 additions & 0 deletions RFC-wrangler-compile.md

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions packages/miniflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,10 @@ export class Miniflare {
readonly #runtime?: Runtime;
readonly #removeExitHook?: () => void;
#runtimeEntryURL?: URL;
// The most recent `workerd` config assembled by `#assembleAndUpdateConfig()`.
// Exposed (alpha) via `unstable_getConfig()` so tooling (e.g. `wrangler compile`)
// can transform it into a standalone bundle without re-deriving the service graph.
#lastAssembledConfig?: Config;
publicUrl?: string;
#socketPorts?: SocketPorts;
#runtimeDispatcher?: Dispatcher;
Expand Down Expand Up @@ -2415,6 +2419,7 @@ export class Miniflare {
loopbackPort,
this.#devRegistry.isEnabled()
);
this.#lastAssembledConfig = config;
const configBuffer = serializeConfig(config);

// Get all socket names we expect to get ports for
Expand Down Expand Up @@ -2663,6 +2668,26 @@ export class Miniflare {
return new URL(this.#runtimeEntryURL.toString());
}

/**
* Returns the `workerd` {@link Config} most recently assembled for this
* instance, waiting for initialisation to complete first.
*
* This is an alpha API intended for tooling that needs the fully-resolved
* service graph (e.g. `wrangler compile`, which transforms it into a
* standalone bundle via {@link toStandaloneConfig}). The shape is not yet
* stable and may change without notice.
*/
async unstable_getConfig(): Promise<Config> {
this.#checkDisposed();
await this.#initPromise;
await this.#runtimeMutex.drained();
assert(
this.#lastAssembledConfig !== undefined,
"Config has not been assembled yet"
);
return this.#lastAssembledConfig;
}

async #registerWorkers(): Promise<void> {
if (!this.#devRegistry.isEnabled()) {
return;
Expand Down Expand Up @@ -3235,6 +3260,7 @@ export * from "./http";
export * from "./plugins";
export * from "./runtime";
export * from "./shared";
export * from "./standalone";
export * from "./workers";
export * from "./merge";
export * from "./zod-format";
Expand Down
Loading
Loading