Skip to content

Tracking: Bundled-Dev (Full Bundle) mode — Phase 3 (CSS HMR & template coverage) #10022

Description

@h-a-n-a

Sub-tracker of #9030 (🎯 Full Bundle Mode) for Phase 3 — CSS HMR & template coverage. Mirrors Milestone 3 of the FBM roadmap (#153, Milestone 6) / Phase 3 of the Vite bundled dev mode roadmap.

Goal

  • Deliver proper CSS HMR
  • Validate FBM across all create-vite templates

Client-side (CSR) gaps found along the way are tracked in Phase 2 (#10019), not here.

CSS HMR

  • Emit CSS as real CSS files, with CSS HMR on them. Meta-frameworks need this to link CSS in the HTML without crawling the module graph, which is empty under FBM (sapphi-red's comment). Done when the hmr cases it swaps out link tags and CSS update preserves query params pass under bundled dev. (no issue yet)

Non-JS modules

From the non-JS module audit (gist).

  • .json5 is parsed as JavaScript, so the build fails. Rolldown has no json5 module type. (no issue yet) · mid priority

Template coverage

From the create-vite template audit (gist): 18/18 built-in templates examined, 6 fail, 3 root causes. 13 SSR templates wait on Phase 4.

References

Activity

  1. filipsobol commented on Jul 6, 2026

    @filipsobol

    We've been running experimental.bundledDev as the dev server, and we're very happy with it. We did have to build a few ugly workarounds along the way, and since this tracker already covers most of what we hit, I wanted to share our findings in one place. Our plugin implementations and the app itself are open source, so I'm happy to post links to both if that's useful.

    1. hotUpdate / handleHotUpdate never called (tracked here and in Tracking: Bundled-Dev (Full Bundle) mode — Phase 2 (Complete CSR support) #10019) - Confirming from our side: handleHMRUpdate() returns early under bundledDev before the plugin hook loop, and the dev-engine path (BundledDev.onHmrUpdates → handleHmrOutput) has no extension point. Our plugin needs to suppress full reloads and show a “refresh available” prompt instead, so we currently monkey-patch server.environments.client.bundledDev internals.

    2. Stale HTML after editing an entry (tracked here as “re-serves stale markup”) - Confirming this one too: editing an HTML entry triggers a full reload, but the browser reloads into the stale initial-build page — only a server restart picks up the change. On the Vite side, .html is served by indexHtmlMiddleware from bundledDev.memoryFiles, and handleHmrOutput re-stores memory files only on the Patch branch, never on FullReload, so the edited HTML never reaches the served output. Our workaround wraps bundledDev.memoryFiles.get and splices the built <head> with the current source read from disk — it works, but we'd love to delete it.

    3. Static files under the project root 404 — this one doesn't seem to be tracked here or in Tracking: Bundled-Dev (Full Bundle) mode — Phase 2 (Complete CSR support) #10019. In bundled dev only triggerLazyBundlingMiddleware and memoryFilesMiddleware are registered, so serveStaticMiddleware never runs, and anything under root that isn't in the bundle or publicDir 404s (e.g., /package.json), while the same URL works in regular dev. The same applies to non-entry .html files (e.g., iframe target pages), which indexHtmlMiddleware serves only from memoryFiles in bundled dev. This bites MPAs and test harnesses that keep fixtures (images, CSS, iframe target pages) next to their HTML entries, referenced via constructed URLs that never enter the module graph. Right now we work around it with a configureServer middleware that's basically a worse copy of serveStaticMiddleware.

    All of the above issues were verified against Vite 8.1.3.

  2. sapphi-red commented on Aug 21, 2026

    @sapphi-red
    Member
    • Proper CSS HMR — investigate first, then decide. Today FBM reuses Vite's existing CSS HMR (Rolldown isn't involved), and the audit confirms css, css-modules, scss, SugarSS, Less, Stylus and ?raw/?inline forms all HMR correctly. Confirm there's a real benefit (suspected: @import performance) before building a Rolldown-native path; if none, keep "reuse Vite" and close. (no issue yet)

    I've noticed one thing that may require this.

    Currently, Vite injects CSS from the JS in dev. In many meta-frameworks, they crawl the module graph and inject the URLs of CSS to the HTML to avoid FOUC. The problem here is that these URLs are not an explicit entrypoint. For now, it should be fine to rely on the unbundled dev behavior for that as it would only cause the duplicate compilation of those CSS files, but it's not ideal for performance.

    The way to solve this would be to generate the CSS files as CSS files (rather than using JS to inject them) and implement CSS HMR. That would allow the meta-frameworks to remove those crawl completely.

  3. changed the title [-]Tracking: Full Bundle Mode — Phase 3 (CSS HMR & template coverage)[/-] [+]Tracking: Bundled-Dev (Full Bundle) mode — Phase 3 (CSS HMR & template coverage)[/+] on Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Fields

Priority

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions