fix(atproto-comments): ship a Svelte-external build to fix hydration crash (#7)#8
Merged
Merged
Conversation
…crash The client build bundled its own Svelte runtime. In a SvelteKit/Vite app — which has its own Svelte — that put two Svelte runtimes on the page, and under `experimental.async` the app's async-boundary hydration would cross into the component's separate runtime and dereference a null effect, crashing with "Cannot read properties of null (reading 'f')" and wiping a correctly server-rendered thread (#7). Emit `dist/client-svelte`/`dist/server-svelte` (Svelte marked external) and declare a `svelte` export condition pointing at them, so bundler consumers dedupe the component onto the app's single Svelte runtime. The default `dist/client` (Svelte bundled) is unchanged and still serves the CDN / bare-`import` drop-in, which has no app Svelte to dedupe against. The vendored direct-props HydrationHost is now applied to every build variant (matched by outDir/entry rather than array index). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W9oixH2t2npbf9u3ara93J
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.
Fixes #7.
Root cause
@svebcomponents/atproto.comments's client build bundled its own Svelte runtime. In a SvelteKit/Vite app — which has its own Svelte — that put two Svelte runtimes on the page. Underexperimental.async, the app's async-boundary hydration (#hydrate_resolved_content→legacy-client) crossed into the component's separate runtime and dereferenced a null effect:The correctly server-rendered thread was then wiped on the client, leaving only the header. The crash only surfaced through the async wrapper path (the documented self-fetch SSR tier), which is why smaller/synchronous setups didn't hit it.
Fix
The build already supports a Svelte-external variant (
@svebcomponents/build≥ 0.3.1:externalSvelte+pluginDedupe+ the hydration-host bundling); this component just never opted in.package.json— declare asvelteexport condition on.and./ssr, pointing at newdist/client-svelte/dist/server-sveltebuilds.svebcomponents.config.ts— emit those Svelte-external variants and apply the vendored direct-propsHydrationHostto every build variant (matched byoutDir/entry, not array index).Bundler consumers (SvelteKit, Vite) resolve the
sveltecondition and dedupe the component onto the app's single Svelte runtime, so the crash is gone by construction — there is only one runtime, so there is no cross-runtime effect to corrupt. The defaultdist/client(Svelte bundled) is unchanged and still serves the CDN / bare-importdrop-in, which has no app Svelte to dedupe against.Verification
client-svelte/server-svelteexternalize Svelte; the vendored host is compiled into every variant;test(11),svelte-check(0 errors),publint, andeslintall pass.new-theosteiner.de, the reporter's app, tested via a packed tarball): the duplicate runtime is eliminated — the optimized component dep went from 2 bundled-runtime markers to 0 and now imports the app's sharedruntime-*.jschunk. The page still hydrates: 227 → 227 comments, zero page errors.Consumer follow-up
After publish, consumers just
pnpm update @svebcomponents/atproto.comments— no app changes, and anyssr.noExternalentry for this component can be dropped.🤖 Generated with Claude Code