fix(site-kit): the shell reads header/footer once; an empty flag sprite loads its bodies (D-027) - #63
Merged
Merged
Conversation
…ads its bodies (D-027)
AskLinq shipped site-kit 0.12.0 and its flag menu became an empty box in
every browser. The server HTML carried every symbol; in the live DOM the
sprite was empty and the trigger's <use> pointed at a uid the server never
wrote. Almost every header element had lost its hydration key — only the
two eagerly built `actions` anchors kept theirs.
`header={{ … }}` compiles to a getter. MarketingShell spread `props.header`
straight into SiteHeader, so every prop read re-evaluated the literal and
rebuilt any JSX built eagerly inside it, consuming hydration keys — a
different number of times on the server than in the browser. From the
first drift the client rebuilt the header from templates: a fresh, empty
sprite, a new uid. The sprite (0.11.0) was simply the first part of the
header that depended on hydration adopting the server markup.
Two guards. MarketingShell reads header and footer once through createMemo,
so an eager prop costs the same keys on both sides whatever the consumer
did. FlagSprite decides "no server HTML" by looking at the element
(childElementCount) rather than the hydration context, so a sprite that
reaches the client empty loads its bodies whatever the reason.
tests/site-kit-hydration.test.mjs server-renders the shell with an
eagerly built action, hydrates it in jsdom with the browser build, and
asserts zero lost server keys and 14 surviving symbols; a second case
empties the sprite before hydration and expects it refilled. Both were
red against the previous code. The contracts pin on sharedConfig.context
moves to the new mechanism. Changeset (patch), README en/ko, D-027.
…urce-only gate The source-contracts CI job checks out without installing or building; the hydration test needs the workspace's solid-js and jsdom and a built site-kit. It moves to verify:site-kit:ui, right after the package build.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
AskLinq's flag menu went blank on site-kit 0.12.0 (owner report, within two hours of devslab-kr/asklinq#436). Server HTML had every symbol; the live DOM had an empty sprite and a
<use>pointing at a uid the server never wrote. Nearly the whole header had lost its hydration keys.header={{ … }}compiles to a getter;MarketingShellspreadprops.headerstraight intoSiteHeader, so each prop read re-evaluated the literal and rebuilt the eageractionsJSX inside it, consuming hydration keys a different number of times on the server than in the browser. The client rebuilt the header from templates. The sprite (0.11.0, D-020) was the first header part whose correctness required hydration to adopt server markup — the<select>era had the same drift, invisibly.What
MarketingShellreadsheaderandfooteronce (createMemo) — an eagerly built prop costs the same keys on both sides.FlagSpriteloads bodies when the element is empty (childElementCount), not when "not hydrating" — a drifted hydration no longer leaves a blank box.tests/site-kit-hydration.test.mjs(stage3-4 gate): SSR with the server build → hydrate with the browser build in jsdom → zero lost server keys, 14 symbols,<use>resolves; plus an emptied-sprite case. Both red before the fix.sharedConfig.contextmoved to the new mechanism. Changeset (patch), README en/ko, D-027.Verify
pnpm run verifygreen,verify:source:stage3-445/45, site-kit vitest green. First consumer: AskLinq bumps to 0.12.1 with its ownget actions()fix (asklinq D-137); production check in a real browser after deploy.왜
AskLinq가 site-kit 0.12.0을 소비하자 국기 메뉴가 빈 칸이 됐다. 서버 HTML엔 심볼이 다 있었고 라이브 DOM엔 스프라이트가 비어 있었으며 헤더 대부분이 하이드레이션 키를 잃었다.
header={{ … }}는 게터로 컴파일되는데 셸이props.header를 그대로 펼쳐 prop마다 리터럴과 즉시 JSX가 다시 만들어지며 키를 소모했고, 서버와 브라우저의 횟수가 달랐다.무엇
MarketingShell이header·footer를 한 번만 읽는다(createMemo).FlagSprite는 하이드레이션 여부가 아니라 엘리먼트가 비었는지로 본문 로드를 결정한다.