Skip to content

Vite 8.1 + Rolldown 1.1.2 upgrade, with experimental bundled dev mode (off by default)#730

Open
natew wants to merge 3 commits into
mainfrom
vite-8.1-upgrade
Open

Vite 8.1 + Rolldown 1.1.2 upgrade, with experimental bundled dev mode (off by default)#730
natew wants to merge 3 commits into
mainfrom
vite-8.1-upgrade

Conversation

@natew

@natew natew commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Upgrades One to Vite 8.1.0 + Rolldown 1.1.2, and adds an experimental bundled dev mode (Vite's FullBundleDevEnvironment) behind an opt-in flag:

one({ web: { experimentalBundledDev: true } })

The upgrade itself (normal/unbundled dev + prod builds) is the shippable win. Bundled dev mode is wired up and renders/hydrates, but has known upstream blockers documented below — it's off by default and should stay that way until those land.

Why upgrade (independent of bundled mode)

Vite 8's headline is Rolldown becoming the single Rust bundler (replaces Rollup + esbuild):

  • ~10–30× faster production builds (Rust)
  • Oxc-powered transforms/minify (@vitejs/plugin-react v6)
  • Unified bundler for dep pre-bundling + build → fewer dev/prod drift surprises

Normal dev is unchanged vs Vite 7, so the build-side win lands regardless of dev mode.

Bundled dev mode — what it is

A single rolldown-powered client bundle in dev instead of unbundled ESM (~4× fewer requests). Four One-specific problems had to be solved to make it work (asset-import inlining, lazyBarrel off, shimMissingExports, react-refresh preamble) — see notes/vite-8.1-bundleddev-findings.md and bundledDevPlugin.ts. All new code paths are gated on the flag; normal dev is unaffected.

Verified: homepage + routes render & hydrate, client <Link> nav + browser back/forward work, 0 console errors (one-basic + tamagui.dev, cold + warm).

⚠️ Findings: bundled mode is NOT production-ready (3 upstream blockers)

All three live in the vite / rolldown bundled-dev substrate, not One, and none affect prod buildsbundledDevPlugin is gated on command === 'serve', so production output is untouched.

1. HMR is broken and crashes the dev server (blocker) — upstream Vite 8.1.0 bug

Live-tested (playwright, edit a file, browser connected, no reload): the edit (a) never applies to the DOM — Fast Refresh is dead — and (b) crashes the whole dev server seconds later with RangeError: Maximum call stack size exceeded (exit 7). Root cause is stock vite 8.1.0 DevEnvironment.invalidateModule:

invalidateModule(m, _client) {
  if (this.bundledDev) { this.invalidateModule(m, _client); return; }  // self-recurses → stack overflow
  ... // the real HMR invalidation logic only runs on the non-bundledDev path
}

Confirmed contrast: normal (unbundled) dev on this same branch applies edits and the server stays up (Fast Refresh works, 0 errors); with no browser attached the edit doesn't crash (the crash needs a connected client to send the invalidate). Needs an upstream vite fix (or a local patch-package) before bundled dev is daily-usable.

2. matchMedia "Illegal invocation" on cold load — rolldown interop codegen

@tamagui/web's matchMedia helper re-exports the unbound native window.matchMedia. Rolldown's bundled-dev interop compiles the call as ns.matchMedia(q) (this = module namespace) instead of the detached (0, ns.matchMedia)(q) form normal bundlers emit, so native matchMedia throws. Worked around in tamagui with window.matchMedia?.bind(window) (defensive, harmless, worth upstreaming) — but it's a symptom: any const fn = window.nativeThing re-export trips the same bug. Not needed for normal dev / prod builds.

3. __toCommonJS(undefined) cold race on heavily-lazy-split routes — rolldown runtime

/takeout's React.lazy 3D box throws on cold first load from the generated rolldown runtime (CJS dep referenced before init across concurrently-loading lazy blobs); self-recovers on reload. Low severity, cold-only.

Recommendation

Land the Vite 8.1 / Rolldown upgrade for the build-side gains. Keep experimentalBundledDev off by default until at least the upstream vite invalidateModule recursion is fixed. One pre-merge validation still worth doing: a Rolldown prod-build smoke test (the matchMedia-class interop could surface in vite build — untested so far).

Files

  • packages/one/src/vite/plugins/bundledDevPlugin.ts (new) — asset inliner + bundled client rolldownOptions
  • packages/one/src/vite/one.ts, types.ts — wire the flag
  • virtualEntryPlugin.ts, fileSystemRouterPlugin.tsx, devtoolsPlugin.ts — refresh preamble / preload / devtools fixes (all gated on the flag)
  • examples/one-basic/vite.config.ts — demonstrates the flag via BUNDLED_DEV env
  • notes/vite-8.1-bundleddev-findings.md — full writeup

natew added 3 commits June 23, 2026 07:40
pin lazyBarrel off in prod native build (rolldown 1.1 flipped the default)

Agentbus-Session: ab-mqqwiegt-38564
…ndleDev)

Agentbus-Session: ab-mqrcxyt6-19898
@railway-app

railway-app Bot commented Jun 24, 2026

Copy link
Copy Markdown

🚅 Deployed to the one-pr-730 environment in onestack.dev

Service Status Web Updated (UTC)
one ❌ Build Failed (View Logs) Web Jun 24, 2026 at 1:54 am

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.

1 participant