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

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions