github cloudflare/agents @cloudflare/worker-bundler@0.1.2

Patch Changes

  • #1334 77c8c9c Thanks @threepointone! - createWorker and createApp now accept a handful of extra esbuild knobs that previously required forking or patching the package:

    • jsx ("transform" | "preserve" | "automatic")
    • jsxImportSource
    • define (compile-time constant replacement)
    • loader (per-extension loader overrides — e.g. { ".svg": "text", ".wasm": "binary" }; built-in handling for .ts/.tsx/.js/.jsx/.json/.css is preserved unless overridden, and longer extensions match first so ".d.ts" wins over ".ts"). The accepted values are deliberately narrowed to the portable BundlerLoader set (js/jsx/ts/tsx/json/css/text/binary/base64/dataurl) — esbuild-specific loaders like file/copy/empty/default are intentionally excluded. file/copy would silently break in this bundler today (they emit secondary output files that get discarded), and anything outside the portable set should go through the plugin escape hatch instead.
    • conditions (package export conditions, e.g. ["workerd", "worker", "browser"])

    The first five are re-typed locally (JsxMode, BundlerLoader) so the published .d.ts does not import from esbuild-wasm — a future bundler swap is a refactor, not a breaking type change.

    For advanced consumers (RSC-style transforms, custom asset pipelines, codegen) there is also an explicit escape hatch:

    __dangerouslyUseEsBuildPluginsDoNotUseOrYouWillBeFired?: unknown[]

    The deliberately unwieldy name is the API contract: this option is not covered by semver, can change shape or be removed in any release, and ties the caller to esbuild's plugin shape — if this package switches bundlers, plugins authored against it will break. It is typed as unknown[] at the public boundary (cast Plugin[] from esbuild-wasm when passing in) so the published types don't acquire a hard dependency on esbuild. User plugins run before the internal virtual-filesystem plugin, so their onResolve/onLoad claims fire first.

    In createApp, all of these options apply to both the server and client bundles.

    The internal bundleWithEsbuild signature was refactored from a long positional argument list to a single options object so future bundler knobs can be added without churning every call site. This is an internal change; no public API moved.

    Inspired by #1321 — thanks @bndkt for the draft and the RSC-on-Workers proof-of-concept that motivated it.

  • #1335 e59388d Thanks @threepointone! - Fix: don't crash with Cannot find package 'gojs' when imported from Node.

    Previously, bundler.ts did a top-level static import esbuildWasm from "./esbuild.wasm". In the Workers runtime that resolves to a WebAssembly.Module natively, but in Node 22+ (e.g. Vitest on GitHub Actions CI) Node's experimental ESM-WASM loader actually parses the file and tries to resolve esbuild-wasm's Go-runtime import namespace gojs as an npm package. That surfaced as the deeply confusing error reported in #1306:

    Cannot find package 'gojs' imported from
    .../@cloudflare/worker-bundler/dist/esbuild.wasm
    

    Two changes:

    • The ./esbuild.wasm import is now lazy — it lives inside initializeEsbuild() as a dynamic import("./esbuild.wasm") call instead of a module-level static import. The package is now safely importable from any JavaScript runtime.
    • Before evaluating that dynamic import, the bundler checks navigator.userAgent === "Cloudflare-Workers". If it's not running inside workerd, it throws an actionable error pointing the caller at @cloudflare/vitest-pool-workers instead of letting Node surface the cryptic gojs resolution failure.

    A side benefit: createWorker({ bundle: false }) (transform-only mode, which never invokes esbuild) now also works in Node, because the WASM is never loaded on that code path.

    The README now also calls out the Workers-only requirement near the top.

    While in there, sharpened a handful of unhelpful error messages to include actionable context:

    • "Entry point/Server entry point/Client entry point ... not found" now lists the user-provided files in the bundle (skipping node_modules/) so it's obvious whether the path is mistyped vs. missing entirely.
    • "Could not determine entry point" now spells out the full priority list it tried (entryPoint option → wrangler mainpackage.json → defaults).
    • npm registry errors include the package name, version, registry URL, and HTTP status text — e.g. Registry returned 404 Not Found for "hno" at https://registry.npmjs.org/hno (package not found — check the name in package.json or set the registry option if it lives on a private registry).
    • The npm fetch-timeout error names the URL and notes the registry was slow/unreachable from the Worker.
    • "Invalid package.json" includes both the path and the underlying parse error.
    • "No output generated from esbuild" now names the entry point and explains the two real-world causes (a custom plugin claiming the entry without returning contents, or the entry resolving to an externalised module).

Don't miss a new agents release

NewReleases is sending notifications on new releases.