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.
Cloudflare.ZarazConfig
Section titled “Cloudflare.ZarazConfig”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. Withdelete: true, destroy restores Cloudflare’s defaults (including resettingworkflowto real-time mode). - Typed Zaraz event helpers ship as
defineZarazEvents.
Thanks Alex for the contribution. (#371)
Bundle analyzer for Workers
Section titled “Bundle analyzer for Workers”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.
Cloudflare.Artifacts in dev
Section titled “Cloudflare.Artifacts in dev”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
exitHookthatSIGKILLs the entire process group when the parent exits, plus a scoped finalizer for the graceful path. Danglingworkerdprocesses are gone. - Sessions are cached per
(serverEntryUrl, alchemyContext, stack)and respawned automatically if the child dies mid-session. RpcProvider.providerServicesEffectlets 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* () { /* … */ }), );Also in this release
Section titled “Also in this release”- Vite-style
?rawimports in the Worker bundler —import 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/namespaceIdin the local provider output, makes the localnamespaceIddeterministic 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 devnow honors your Workersassetsconfig — the configured asset behavior was previously ignored in local dev (#403).mysql2no longer errors at bundle time in the Worker bundler (#403).x-forwarded-forandx-forwarded-protoheaders are now forwarded on incoming requests inalchemy dev(#403).- Rolldown bumped to 1.0.1 stable — out of pre-release (#409).
@alchemy.run/node-utilsimport 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).
Contributors
Section titled “Contributors”Thanks to everyone who shipped code in this beta:
- Alex —
Cloudflare.ZarazConfig(#371) - Michael K — CLI watcher warning filter (#124)
- sam — privacy page styling cleanup (#398)