Skip to content

fix(theme-yun): render YunAdBoard placeholder as a comment node to fix SSR hydration (#711) - #712

Merged
YunYouJun merged 3 commits into
mainfrom
fix/711
Jun 22, 2026
Merged

fix(theme-yun): render YunAdBoard placeholder as a comment node to fix SSR hydration (#711)#712
YunYouJun merged 3 commits into
mainfrom
fix/711

Conversation

@YunYouJun

Copy link
Copy Markdown
Owner

Summary

Fixes #711 — opening a post page directly throws TypeError: Failed to execute 'replaceChild' on 'Node': parameter 1 is not of type 'Node' on any page that renders YunLayoutLeft.

Root cause

YunAdBoard.vue is an empty, user-overridable placeholder. It rendered a bare <template />, which Vue's SSR compiler serializes as a real <template></template> element:

// ssrRender (raw `<template />`)
_push(`<template></template>`)

On the client the component resolves to nothing, so during hydration Vue tries to replace that SSR <template> DOM node with nullreplaceChild throws.

Fix

Render the placeholder with <template v-if="false" /> so it emits a comment node consistently in both SSR and on the client:

// ssrRender → `<!---->`     // client render → createCommentVNode("v-if", true)

SSR and client now agree, so hydration matches.

Why not <div /> (the fix suggested in the issue)?

A comment node is not a flex item, so it adds no gap to the parent .yun-layout-left (flex + gap-4) layout. An empty <div> is a flex item and would reintroduce the exact spacing bug that commit ab57216f ("empty template for YunAdBoard parent gap size") originally fixed by switching <div /><template />. <template v-if="false" /> satisfies both constraints: no hydration crash and no gap.

Test

Adds test/client/yun-adboard.test.ts, which compiles the real YunAdBoard.vue, and asserts:

  1. its SSR output contains no raw <template> element;
  2. it renders nothing visible (comment-only);
  3. it hydrates in jsdom with no mismatch.

A control case confirms the old <template /> form serializes back to a <template> element (the regression guard). Reverting the component to the broken form makes the suite fail — test 2 reproduces the original TypeError exactly.

Verification

  • pnpm run build
  • pnpm lint
  • pnpm typecheck
  • pnpm test ✅ (the 2 failing test/build/* cases require a prior pnpm demo:build and are unrelated to this change)

🤖 Generated with Claude Code

…e to fix SSR hydration (close #711)

The empty `<template />` placeholder in YunAdBoard is serialized as a real
`<template></template>` element during SSR. On hydration Vue resolves the
component to null and tries to replace that DOM node, throwing
`TypeError: Failed to execute 'replaceChild' on 'Node'` on every page that
renders YunLayoutLeft (e.g. opening a post directly).

Switching to `<template v-if="false" />` makes the component render a comment
node consistently in both SSR and on the client, so hydration matches.

A comment node is also not a flex item, so this keeps the no-gap behaviour of
the parent `.yun-layout-left` layout that ab57216 introduced — the reason the
placeholder was changed from `<div />` to `<template />` in the first place.
Reverting to `<div />` (as suggested in the issue) would fix hydration but
reintroduce that gap.

Adds a regression test that compiles the real component, asserts its SSR output
contains no raw `<template>` element, and verifies it hydrates without a
mismatch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
valaxy-docs-dev Ready Ready Preview, Comment Jun 22, 2026 2:40am

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

@github-actions
github-actions Bot temporarily deployed to pull request June 22, 2026 02:06 Inactive
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 22, 2026

Copy link
Copy Markdown

Deploying valaxy with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9286950
Status: ✅  Deploy successful!
Preview URL: https://cd4837e7.valaxy.pages.dev
Branch Preview URL: https://fix-711.valaxy.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 22, 2026

Copy link
Copy Markdown

Deploying valaxy-api with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9286950
Status: ✅  Deploy successful!
Preview URL: https://8a69ae42.valaxy-api.pages.dev
Branch Preview URL: https://fix-711.valaxy-api.pages.dev

View logs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an SSR hydration crash in valaxy-theme-yun where the empty, user-overridable YunAdBoard placeholder was serialized as a real <template> element in SSR, causing Vue hydration to attempt an invalid DOM replacement when the client renders nothing.

Changes:

  • Updated YunAdBoard.vue to render the placeholder as a stable comment node via <template v-if="false" />, avoiding both hydration errors and unwanted flex-gap layout effects.
  • Added a Vitest + jsdom regression test that compiles the real SFC template, asserts SSR output contains no raw <template> element, and verifies hydration produces no mismatch warnings/errors.
  • Added a control test documenting the previous broken <template /> behavior to prevent regression.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
packages/valaxy-theme-yun/components/YunAdBoard.vue Switches the placeholder output to a comment node (SSR + client consistent) to prevent hydration crashes without affecting layout gap.
test/client/yun-adboard.test.ts Adds a regression test suite covering SSR serialization and jsdom hydration behavior for the real YunAdBoard SFC.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/client/yun-adboard.test.ts Outdated
Ensures the console.error/warn spies in the YunAdBoard hydration test are
always restored, even if the mount assertion throws on a regression, so the
mocks never leak into later tests. Addresses Copilot review feedback on #712.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread test/client/yun-adboard.test.ts
Drop the redundant named imports from `vue` and `vue/server-renderer` and call
`Vue.createSSRApp` / `serverRenderer.renderToString` off the namespace objects
(which are already needed wholesale by the compiled render functions). Addresses
Copilot review feedback on #712.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to pull request June 22, 2026 02:39 Inactive
@YunYouJun
YunYouJun requested a review from Copilot June 22, 2026 02:41
@YunYouJun YunYouJun changed the title fix(valaxy-theme-yun): render YunAdBoard placeholder as a comment node to fix SSR hydration (#711) fix(theme-yun): render YunAdBoard placeholder as a comment node to fix SSR hydration (#711) Jun 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@YunYouJun
YunYouJun merged commit 57f36c7 into main Jun 22, 2026
15 checks passed
@YunYouJun
YunYouJun deleted the fix/711 branch June 22, 2026 02:46
@github-actions

Copy link
Copy Markdown
Contributor

Yun Good!

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.

fix(valaxy-theme-yun): empty template in YunAdBoard causes SSR hydration failure

2 participants