Skip to content

fix: prepend the server-component bootstrap to the hydration script - #294

Closed
brenelz wants to merge 1 commit into
solidjs:nextfrom
brenelz:fix/sc-bootstrap-head-shift
Closed

fix: prepend the server-component bootstrap to the hydration script#294
brenelz wants to merge 1 commit into
solidjs:nextfrom
brenelz:fix/sc-bootstrap-head-shift

Conversation

@brenelz

@brenelz brenelz commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Problem

With serverFunctions.components on a generated entry, hydration reports every client component that sits in a server-component slot as unclaimed server markup:

Hydration completed with 9 unclaimed server-rendered node(s):
  <form _hk="sc-84ece717-0-appView-search-0" class="search" role="search">…
  <a _hk="sc-84ece717-0-appView-editButton-0" href="/new" class="edit-button…
  <div _hk="sc-a112e1b2-0-noteListView-item#0-1" class="sidebar-note-list-item…
  …

Cause

ssrServe injects the placeholder registry as its own <script> immediately after the opening <head> tag. The ordering that anchor buys is real — the render plugin serializes placeholders as self._$SC.r(id), so the registry must be defined before the hydration data script runs, and anchoring on </head> lands after <HydrationScript /> — but the injected node becomes an unexpected first child of <head>, which Solid's structural hydration cursor walks.

Fix

Prepend the bootstrap source to the hydration runtime script that is already in the document, instead of adding a script node. Same ordering guarantee, no extra node.

The turnkey frames check is updated to assert the new placement: the bootstrap and window._$HY must live in the same <script>, with the bootstrap first and still ahead of any _$HY.r[ data.

🤖 Generated with Claude Code

The generated-entry handler injected the placeholder registry as its own
`<script>` right after the opening `<head>` tag. That anchor is correct for
ordering — the render plugin serializes placeholders as `self._$SC.r(id)`,
so the registry has to exist before the hydration data script runs — but the
extra node becomes an unexpected first child of `<head>`, and Solid's
structural hydration cursor walks that.

Prepend the bootstrap to the hydration runtime script instead: it still runs
before any hydration data, and the document's head structure is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: da24711

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

This PR includes changesets to release 1 package
Name Type
vite-plugin-solid 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 Jul 31, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: da24711

@ryansolid

Copy link
Copy Markdown
Member

Superseded by a runtime-level fix. As of @dom-expressions/runtime 0.50.0-next.37, serialized server-component references self-bootstrap the _$SC registry: each hydration script's first reference carries the bootstrap as an idempotent expression, so definition and read are atomic and ordering is correct by construction — no integration needs to place a bootstrap anywhere. 030fc89 (shipping in 3.0.0-next.22) removes the head-open splice entirely, which fixes the unclaimed-node / positional-drift problem this PR targets without keeping the plugin responsible for bootstrap placement. The turnkey document check was also updated to assert the new invariant (no bare self._$SC.r( read may precede a definition). Thanks for the diagnosis — it was exactly right about the injected node being walked by the hydration cursor.

@ryansolid ryansolid closed this Aug 5, 2026
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.

2 participants