Skip to content

fix: send server environments their reload signal on hot update#282

Open
brenelz wants to merge 1 commit into
solidjs:nextfrom
brenelz:fix/server-env-reload-signal
Open

fix: send server environments their reload signal on hot update#282
brenelz wants to merge 1 commit into
solidjs:nextfrom
brenelz:fix/server-env-reload-signal

Conversation

@brenelz

@brenelz brenelz commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Problem

hotUpdate returns [] for every non-client environment. The intent (per the comment) is sound: solid-refresh only injects HMR boundaries into client modules, so letting Vite's propagation run in server environments dead-ends into full-reload messages that race client-side HMR.

But emptying the modules array also suppresses the only reload signal that environment-runner based servers rely on. With nitro's Vite integration (nitro/vite), SSR runs in a persistent module runner inside a dev worker — evaluated modules live until that environment's hot channel receives a full-reload. Vite's default dead-end propagation would send exactly that, but it never runs because the modules array arrives empty (and downstream plugins like nitro's own hotUpdate are blinded the same way, since Vite feeds each hook the previous hook's filtered array).

Net effect in a vite-plugin-solid + nitro app: edit any SSR-rendered module (every route component) → client updates via HMR, server keeps rendering the old module until a manual dev-server restart → hydration key/markup mismatches on the next load (unclaimed server nodes, and in our repro a Cannot read properties of null (reading 'nextSibling') crash during hydration).

Full investigation with traces: nitrojs/nitro#4472 (this plugin's role: comment). The staleness also needs a nitro-side fix for its worker reload (nitrojs/nitro#4473) — but without this change, the reload is never even requested.

Fix

Keep the suppression, but send { type: "full-reload" } on the environment's own hot channel first (when the changed file has modules in that environment's graph):

  • For runner-based environments (nitro's dev worker), the channel reaches the runner — SSR picks up the edit.
  • For the default ssr environment, the channel is a no-op — nothing changes.
  • It is never the browser websocket, so the client-HMR race the original code guards against stays suppressed.

Verification

Reproduced and verified against a Solid 2 + nitro/vite playground (vite 8.0.10, vite-plugin-solid 3.0.0-next.15, nitro 3.0.260610-beta with the nitrojs/nitro#4473 fix applied):

  • Before: editing a route component leaves SSR output byte-identical across reloads until the dev server restarts; hydration mismatches on reload.
  • After (this patch alone, no userland workarounds): consecutive edits are reflected in SSR within ~2s each, hydration is clean, and client HMR still applies edits in place with page state preserved (no full browser reloads).

pnpm build (rollup + tsc) passes.

Returning [] from hotUpdate for non-client environments suppresses the
full-reload messages that would race client HMR, but it also suppresses
the only signal environment-runner based servers (e.g. nitro's dev
worker) have for re-evaluating modules: with the modules array emptied,
Vite's dead-end propagation never fires the environment-level
full-reload, so SSR keeps serving stale modules until the dev server is
restarted — and hydration mismatches against the freshly HMR-updated
client.

Keep the suppression, but send the reload on the environment's own hot
channel first. For runner-based environments that channel reaches the
runner; for the default ssr environment it is a no-op; it is never the
browser websocket, so client HMR stays free of full-reload races.
@changeset-bot

changeset-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: b50e5c5

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/vite-plugin-solid@282

commit: b50e5c5

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