Skip to content

bundledDev: react-refresh preamble in entry chunk executes after shared chunks in MPA apps #1191

@hirish

Description

@hirish

Description

When using experimental: { bundledDev: true } with an MPA (appType: "mpa" and multiple HTML entries), the react-refresh preamble (which sets window.$RefreshReg$ and window.$RefreshSig$) is injected via transformIndexHtml in vite:react-refresh-fbm. During the Rolldown build, this becomes an html-proxy inline module in the entry chunk.

With multiple entry points, Rolldown's code splitting creates shared chunks containing component code. Due to ES module evaluation order (imports are evaluated depth-first), shared chunks execute before the entry chunk. The react-refresh-wrapper plugin's synchronous check for window.$RefreshReg$ in those shared chunks throws before the preamble has set it:

Uncaught Error: @vitejs/plugin-react can't detect preamble. Something is wrong.

This affects any MPA React app using bundledDev — Rolldown's default code splitting is sufficient to trigger it when modules are shared between entries, no custom codeSplitting.groups required.

Reproduction

// vite.config.ts
export default defineConfig({
  appType: "mpa",
  experimental: { bundledDev: true },
  build: {
    rolldownOptions: {
      input: {
        app: "entries/app/index.html",
        other: "entries/other/index.html",
      },
    },
  },
})

Both entries import any React component. The component ends up in a shared chunk, which executes before either entry's preamble.

Environment

  • vite: 8.0.8
  • @vitejs/plugin-react: 6.0.0

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions