Skip to content

2.0.0-beta.44 - ZarazConfig & Bundle Analyzer

v2.0.0-beta.44 is a polish release. Two new things worth calling out — a new Cloudflare.ZarazConfig resource and a bundle analyzer plugin for the Worker bundler — plus a batch of bundler and dev-server fixes.

New resource for managing a zone’s Zaraz config — tools, triggers, variables, consent, analytics, and workflow mode — declaratively alongside the rest of your Cloudflare stack.

import * as Cloudflare from "alchemy/Cloudflare";
const zaraz = yield* Cloudflare.ZarazConfig("analytics", {
zone: "example.com",
tools: {
"google-analytics": { /* tool config */ },
},
consent: { enabled: true },
});

A couple of design notes worth knowing:

  • Fields you omit (tools, triggers, variables, workflow) are left alone rather than wiped. This means you can adopt a zone’s existing Zaraz setup incrementally.
  • Destroy is opt-in via delete: true. By default, destroying the resource removes it from Alchemy state and leaves the zone’s Zaraz config intact. With delete: true, destroy restores Cloudflare’s defaults (including resetting workflow to real-time mode).
  • Typed Zaraz event helpers ship as defineZarazEvents.

Thanks Alex for the contribution. (#371)

The Worker bundler can now emit a per-build report describing exactly what ended up in your bundle: chunks, modules, the import graph reachable from each entry point, and which entry pulled in which module.

Opt in via build.bundleAnalyzer on the Worker:

export default class Api extends Cloudflare.Worker<Api>()(
"Api",
{
main: import.meta.filename,
build: { bundleAnalyzer: true },
},
/* ... */
) {}

By default this writes analyze-data.md next to the bundle in .alchemy/bundles/<id>. Pass an object to customize:

build: {
bundleAnalyzer: { fileName: "bundle.json", format: "json" },
}

Under the hood it wraps rolldown’s experimental bundleAnalyzerPlugin, exported as Bundle.bundleAnalyzerPlugin for anyone composing their own bundles. (#405)

This replaces the previous build.metafile option, which is now removed.

The Cloudflare.Artifacts binding now works under bun alchemy dev — previously it was only wired up in deployed Workers. No code change required; existing artifact bindings light up locally on upgrade. (#419)

RpcProvider for more reliable local development

Section titled “RpcProvider for more reliable local development”

Until beta.43, local providers (the runtime that backs Cloudflare.Worker, DurableObjectNamespace, etc. under alchemy dev) ran inside an in-process “sidecar” tied to the dev server. That worked, but it leaked: when the dev process exited — Ctrl-C, crash, HMR restart — the child workerd processes it had spawned could survive, holding ports open and consuming memory until you noticed and killed them by hand.

beta.44 refactors this into a generic Local/Rpc* provider abstraction. Local providers now run in their own child process managed by a new RpcSpawner, and the parent talks to them over RPC. Concretely:

  • It registers an exitHook that SIGKILLs the entire process group when the parent exits, plus a scoped finalizer for the graceful path. Dangling workerd processes are gone.
  • Sessions are cached per (serverEntryUrl, alchemyContext, stack) and respawned automatically if the child dies mid-session.
  • RpcProvider.providerServicesEffect lets heavy provider-only layers (e.g. the Cloudflare local runtime and proxy) build lazily inside the child rather than eagerly in the parent — the parent stays lean.

The defining shape for a provider is now thin:

export const LocalWorkerProvider = () =>
RpcProvider.effect(
Worker,
import.meta.resolve(/* ./Local.ts | ./Local.js */),
Effect.gen(function* () { /* … */ }),
);
  • Vite-style ?raw imports in the Worker bundlerimport sql from "./schema.sql?raw" now works, matching the Vite convention for inlining a file as a string (#411).
  • Local Durable Objects hardened — fixes swapped className/namespaceId in the local provider output, makes the local namespaceId deterministic and independent of the binding name, and stops DOs declared on other Workers in the stack from being registered against the current Worker (#408).
  • alchemy dev now honors your Workers assets config — the configured asset behavior was previously ignored in local dev (#403).
  • mysql2 no longer errors at bundle time in the Worker bundler (#403).
  • x-forwarded-for and x-forwarded-proto headers are now forwarded on incoming requests in alchemy dev (#403).
  • Rolldown bumped to 1.0.1 stable — out of pre-release (#409).
  • @alchemy.run/node-utils import resolution fix — resolves an ESM resolution error on Node (#406).
  • CLI filters Bun’s “not in project directory” watcher warning — no more spurious warnings during dev. Thanks Michael K (#124).

Thanks to everyone who shipped code in this beta: