Skip to content

fix: workerd bundling — cache.js lazy import("bun") stays non-literal in dist - #148

Merged
linyiru merged 2 commits into
mainfrom
fix/cache-bun-import
Jul 31, 2026
Merged

fix: workerd bundling — cache.js lazy import("bun") stays non-literal in dist#148
linyiru merged 2 commits into
mainfrom
fix/cache-bun-import

Conversation

@linyiru

@linyiru linyiru commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Closes #141.

The source already guarded the Bun-only redis path with a non-literal specifier, but tsdown/rolldown constant-folds const s = "bun"; import(s) back into a literal import("bun") in dist/cache.js — and cache.ts sits in @junejs/core's root import graph (agent.tscache.ts), so every consumer whose own bundler resolves imports statically (wrangler/esbuild for Workers) failed with Could not resolve "bun", even though the redis path never executes there.

Two parts:

  • The specifier lives in data now — a Map lookup no bundler evaluates. Rebuilt dist carries import(runtimeModules.get("redis")), which esbuild treats as a non-analyzable dynamic import and leaves alone.
  • The invariant is asserted, not assumed — the identical plain-const guard survived folding in agent-models.js and folded in cache.js (the optimizer's inlining is heuristic), so scripts/smoke-packed.sh now greps the packed core dist and fails the packed E2E if a literal import("bun" ever reappears.

Verified: the original repro — bunx wrangler deploy --dry-run on examples/agent-edge — bundles clean (Total Upload 49.32 KiB) against the rebuilt dist; bun run ci green (1084 tests / 0 fail); the redis store's own tests unchanged and passing.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prevents Workers bundlers from statically resolving Bun’s Redis client import.

Changes:

  • Hides the Bun import specifier behind a Map.
  • Adds a packed-dist regression check.
  • Adds a patch changeset.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/core/src/cache.ts Makes the Bun import non-analyzable.
scripts/smoke-packed.sh Checks packed output for literal Bun imports.
.changeset/cache-bun-import.md Documents the bundling fix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/smoke-packed.sh
# source guards this with a data-indirected specifier; assert tsdown didn't
# constant-fold it back (it folded a plain `const s = "bun"; import(s)` once).
echo "→ verifying the packed core dist carries no literal runtime-only imports"
core_dist=$(tar -xzOf "$work"/junejs-core-*.tgz package/dist/cache.js) || {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already addressed in f8f43fa (fix(smoke): build core before inspecting its packed dist) — the guard now runs bun run build in packages/core and REPACKS it before the extraction, mirroring publish.yml's pre-pack build, so the inspected tarball is the artifact npm consumers actually get. Empirically green: the packed job passed on this branch after that commit (32s), and the full local run passes end-to-end. The review snapshot predates the fix commit.

linyiru added 2 commits July 31, 2026 14:38
…ist (#141)

tsdown/rolldown constant-folded the plain-const guard back into a literal
import("bun") in dist/cache.js, and cache.ts is in core's root import
graph — every Workers consumer's bundler (wrangler/esbuild) then failed
with 'Could not resolve "bun"' even though the redis path never executes
there. The specifier now lives in data (a Map lookup no bundler
evaluates); smoke-packed.sh asserts the packed dist stays fold-free (the
same guard survived in agent-models and folded here — inlining is
heuristic, so the invariant is asserted, not assumed). Verified: the
original repro (wrangler deploy --dry-run on examples/agent-edge) bundles
clean.
The smoke tarballs are packed without dist (publish.yml builds before
packing), so the new fold-guard read a file that never exists in the smoke
flow. Build + repack core first — the same pre-pack step publish runs — so
the inspected artifact is the one npm consumers actually get.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (1)

scripts/smoke-packed.sh:65

  • The guard only matches the exact spelling import("bun")/import('bun'). A still-static literal such as import( "bun") (valid output after a formatter change) passes this check even though wrangler will resolve it and fail. Allow whitespace around the call delimiter so the assertion covers literal imports rather than one serialization.
if printf '%s' "$core_dist" | grep -qE 'import\((["'\''])bun'; then

@linyiru
linyiru merged commit 2441c25 into main Jul 31, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

workerd bundling breaks on core/dist/cache.js lazy import("bun") when resolution goes through dist

2 participants