Skip to content

feat: let frontends take part in hot updates - #539

Open
brenelz wants to merge 1 commit into
nextfrom
feat/frontend-hot-update
Open

brenelz wants to merge 1 commit into
nextfrom
feat/frontend-hot-update

Conversation

@brenelz

@brenelz brenelz commented Nov 14, 2026 •

Copy link
Copy Markdown
Contributor

A front end such as ReactiveScript's .rx cannot hot-update its modules today: every edit reloads the page.

Root cause

A front end's output can be shaped so that the refresh pass finds no component to swap. A non-entry .rx module compiles to export default function module(__rt) { … }, a factory the runtime runs once per app, so the pass emits no import.meta.hot.accept. The front end could add its own HMR code, but it has no way to tell that a transform serves a dev client with refresh on. It also cannot shape the module list Vite updates. A front end that compiles a whole program from its entry watches every module from the entry (addWatchFile), so any edit reaches the entry and reloads the page, even when the edited module accepts its own update.

What changed

  • FrontendContext.hot is true when the transform serves a dev client and the refresh pass runs on the output (needRefresh), and false otherwise. It is left unset in the dependency scan and in the stylesheet recompile.
  • Frontend.hotUpdate(context) is optional. It runs in the client environment's hotUpdate, gets { file, modules, read, root }, and returns the modules to update, or nothing to keep Vite's list. The plugin still adds the file's CSS module after it. If the hook throws, the plugin logs a warning and keeps Vite's list. The built-in lazy .rx front end forwards the hook once its package has loaded.

Both are additive, so front ends that do not use them behave as before. ReactiveScript's front end uses them in solidjs/reactivescript#68: it adds its own accept handling when hot is set, and its hotUpdate drops the entry's watch-only modules when only a dependency's components changed.

Verification

  • vitest run: 149 pass. frontends.test.ts checks that hot is true in a client transform and false under SSR, and that the hook's list replaces Vite's, with the CSS module added after.
  • tsc --noEmit is clean.
  • With this branch built and linked into the solid-v2/with-reactivescript template, Playwright checked edits to Counter.rx. Markup, <style> and logic edits hot-swap with no reload and keep the guestbook's entries and the current user. Top-level and entry edits reload.

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Nov 14, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b303c6a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@solidjs/vite-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Nov 14, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@solidjs/vite-plugin@539

commit: b303c6a

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