Skip to content

fix(hydration): respect data-allow-mismatch on conditional branches#12801

Merged
edison1105 merged 5 commits into
mainfrom
edison/fix/12782
Jun 25, 2026
Merged

fix(hydration): respect data-allow-mismatch on conditional branches#12801
edison1105 merged 5 commits into
mainfrom
edison/fix/12782

Conversation

@edison1105

@edison1105 edison1105 commented Feb 1, 2025

Copy link
Copy Markdown
Member

close #12782

Summary by CodeRabbit

  • Bug Fixes

    • Improved hydration mismatch handling so data-allow-mismatch is respected more consistently for nested and conditional/branch-based rendering, including cases involving comment nodes.
    • Continued to warn when mismatches aren’t covered by the allowed mismatch rules, preventing masking of unsupported node-level issues.
  • Tests

    • Added new hydration tests covering conditional rendering and branch mismatch scenarios to validate the updated mismatch-allowance behavior.

@github-actions

github-actions Bot commented Feb 1, 2025

Copy link
Copy Markdown

Size Report

Bundles

File Size Gzip Brotli
runtime-dom.global.prod.js 106 kB (+162 B) 40.2 kB (+52 B) 36.2 kB (+80 B)
vue.global.prod.js 165 kB (+162 B) 60.2 kB (+71 B) 53.6 kB (+101 B)

Usages

Name Size Gzip Brotli
createApp (CAPI only) 48.8 kB 19 kB 17.4 kB
createApp 56.9 kB 22 kB 20.1 kB
createSSRApp 61.4 kB (+162 B) 23.8 kB (+70 B) 21.7 kB (+59 B)
defineCustomElement 63.1 kB 23.9 kB 21.8 kB
overall 71.7 kB 27.4 kB 25 kB

@pkg-pr-new

pkg-pr-new Bot commented Feb 1, 2025

Copy link
Copy Markdown

Open in StackBlitz

@vue/compiler-core

pnpm add https://pkg.pr.new/@vue/compiler-core@12801
npm i https://pkg.pr.new/@vue/compiler-core@12801
yarn add https://pkg.pr.new/@vue/compiler-core@12801.tgz

@vue/compiler-dom

pnpm add https://pkg.pr.new/@vue/compiler-dom@12801
npm i https://pkg.pr.new/@vue/compiler-dom@12801
yarn add https://pkg.pr.new/@vue/compiler-dom@12801.tgz

@vue/compiler-sfc

pnpm add https://pkg.pr.new/@vue/compiler-sfc@12801
npm i https://pkg.pr.new/@vue/compiler-sfc@12801
yarn add https://pkg.pr.new/@vue/compiler-sfc@12801.tgz

@vue/compiler-ssr

pnpm add https://pkg.pr.new/@vue/compiler-ssr@12801
npm i https://pkg.pr.new/@vue/compiler-ssr@12801
yarn add https://pkg.pr.new/@vue/compiler-ssr@12801.tgz

@vue/reactivity

pnpm add https://pkg.pr.new/@vue/reactivity@12801
npm i https://pkg.pr.new/@vue/reactivity@12801
yarn add https://pkg.pr.new/@vue/reactivity@12801.tgz

@vue/runtime-core

pnpm add https://pkg.pr.new/@vue/runtime-core@12801
npm i https://pkg.pr.new/@vue/runtime-core@12801
yarn add https://pkg.pr.new/@vue/runtime-core@12801.tgz

@vue/runtime-dom

pnpm add https://pkg.pr.new/@vue/runtime-dom@12801
npm i https://pkg.pr.new/@vue/runtime-dom@12801
yarn add https://pkg.pr.new/@vue/runtime-dom@12801.tgz

@vue/server-renderer

pnpm add https://pkg.pr.new/@vue/server-renderer@12801
npm i https://pkg.pr.new/@vue/server-renderer@12801
yarn add https://pkg.pr.new/@vue/server-renderer@12801.tgz

@vue/shared

pnpm add https://pkg.pr.new/@vue/shared@12801
npm i https://pkg.pr.new/@vue/shared@12801
yarn add https://pkg.pr.new/@vue/shared@12801.tgz

vue

pnpm add https://pkg.pr.new/vue@12801
npm i https://pkg.pr.new/vue@12801
yarn add https://pkg.pr.new/vue@12801.tgz

@vue/compat

pnpm add https://pkg.pr.new/@vue/compat@12801
npm i https://pkg.pr.new/@vue/compat@12801
yarn add https://pkg.pr.new/@vue/compat@12801.tgz

commit: 8d3774c

@edison1105 edison1105 added ready to merge The PR is ready to be merged. 🍰 p2-nice-to-have Priority 2: this is not breaking anything but nice to have it addressed. scope:hydration labels Feb 1, 2025

@skirtles-code skirtles-code left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It seems like this adds a new type of allowable mismatch. Is there any precedent for this type of mismatch?

If we want to allow this then we may need to consider similar cases, like:

Those seem essentially the same to me.

Comment thread packages/runtime-core/src/hydration.ts Outdated
node: Node,
{ props }: VNode,
): boolean {
return isComment(node) && props != null && hasOwn(props, allowMismatchAttr)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If a node has data-allow-mismatch="class" then I wouldn't expect it to suppress hydration errors for unexpected comment nodes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed by making this a children-scoped node mismatch allowance instead of checking only for the presence of data-allow-mismatch on the client vnode.

The updated logic now checks the parent/server node/client vnode through the same data-allow-mismatch type parsing, so only an empty value or children suppresses node mismatches. class/style/attribute no longer suppress them.

I also added coverage for the flipped v-if case, the v-else branch case, and a data-allow-mismatch="class" negative case.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 55e6ffda-3f5e-4262-ba9c-856d06b248c2

📥 Commits

Reviewing files that changed from the base of the PR and between e896551 and 8d3774c.

📒 Files selected for processing (2)
  • packages/runtime-core/__tests__/hydration.spec.ts
  • packages/runtime-core/src/hydration.ts

📝 Walkthrough

Walkthrough

Hydration mismatch handling now checks node, parent, and vnode data-allow-mismatch sources. New tests cover comment-based v-if, removed branches, v-else, and warning behavior when only child mismatches are allowed.

Changes

Hydration mismatch allowance

Layer / File(s) Summary
Node-aware mismatch allowance
packages/runtime-core/src/hydration.ts
handleMismatch now checks node- and vnode-level data-allow-mismatch sources, and the helper path resolves allowed mismatch types from element, node, and vnode attributes.
v-if hydration tests
packages/runtime-core/__tests__/hydration.spec.ts
New tests cover comment-based v-if, removed branches, v-else, and warning behavior when only child mismatches are allowed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • vuejs/core#14833: Adjusts hydration mismatch reporting to honor data-allow-mismatch in a related hydration path.
  • vuejs/core#14857: Also changes packages/runtime-core/src/hydration.ts mismatch allowance and warning handling.

Suggested labels

:hammer: p3-minor-bug

Suggested reviewers

  • Doctor-wu
  • johnsoncodehk

Poem

A bunny met a v-if ghost,
and children rules did matter most.
With comments, branches, warnings near,
the mismatch faded from the peer.
🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: hydrating branches now respect data-allow-mismatch.
Linked Issues check ✅ Passed The hydration fix and tests address suppressing v-if branch mismatch warnings with data-allow-mismatch.
Out of Scope Changes check ✅ Passed The PR stays focused on hydration mismatch handling and its tests, with no unrelated changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch edison/fix/12782

Comment @coderabbitai help to get the list of available commands.

@edison1105 edison1105 changed the title fix(hydration): handle v-if node mismatch fix(hydration): respect data-allow-mismatch on conditional branches Jun 25, 2026

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
packages/runtime-core/__tests__/hydration.spec.ts (1)

2302-2310: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a positive children token case for vnode-side allowance.

This test covers the empty-attribute fast path, but the new vnode-side helper also relies on parsing data-allow-mismatch="children". Adding that variant would lock down the documented non-empty token behavior for comment-based v-if mismatches.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/runtime-core/__tests__/hydration.spec.ts` around lines 2302 - 2310,
Add a positive vnode-side token test for the comment mismatch case in
hydration.spec.ts, since the current `test('comment mismatch (v-if)')` only
covers the empty `data-allow-mismatch` fast path. Extend the existing
`mountWithHydration`/`expect(container.innerHTML)` coverage to include
`data-allow-mismatch="children"` on the vnode and assert the same no-warning
behavior, so the `data-allow-mismatch` parsing in the vnode-side helper is
covered for non-empty tokens too.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/runtime-core/__tests__/hydration.spec.ts`:
- Around line 2302-2310: Add a positive vnode-side token test for the comment
mismatch case in hydration.spec.ts, since the current `test('comment mismatch
(v-if)')` only covers the empty `data-allow-mismatch` fast path. Extend the
existing `mountWithHydration`/`expect(container.innerHTML)` coverage to include
`data-allow-mismatch="children"` on the vnode and assert the same no-warning
behavior, so the `data-allow-mismatch` parsing in the vnode-side helper is
covered for non-empty tokens too.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b102bf87-b49d-4ab9-aa32-47377be7c70f

📥 Commits

Reviewing files that changed from the base of the PR and between 22f359b and e896551.

📒 Files selected for processing (2)
  • packages/runtime-core/__tests__/hydration.spec.ts
  • packages/runtime-core/src/hydration.ts

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/runtime-core/src/hydration.ts`:
- Around line 404-406: The hydration mismatch check is skipping empty
pre-transition class state because hydration.ts only caches and reads truthy
class values in the Transition flow. Update the logic around content.$cls and
the later propHasMismatch() class comparison so empty string / missing server
class is preserved explicitly for Transition.appear, allowing beforeEnter()
temporary classes to be excluded from mismatch detection. Use the existing
hydration transition hooks paths and the class caching/reading logic in the
relevant hydration helpers to keep the pre-transition class snapshot intact even
when it is empty.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 55e6ffda-3f5e-4262-ba9c-856d06b248c2

📥 Commits

Reviewing files that changed from the base of the PR and between e896551 and 8d3774c.

📒 Files selected for processing (2)
  • packages/runtime-core/__tests__/hydration.spec.ts
  • packages/runtime-core/src/hydration.ts

@coderabbitai coderabbitai Bot 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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/runtime-core/src/hydration.ts`:
- Around line 404-406: The hydration mismatch check is skipping empty
pre-transition class state because hydration.ts only caches and reads truthy
class values in the Transition flow. Update the logic around content.$cls and
the later propHasMismatch() class comparison so empty string / missing server
class is preserved explicitly for Transition.appear, allowing beforeEnter()
temporary classes to be excluded from mismatch detection. Use the existing
hydration transition hooks paths and the class caching/reading logic in the
relevant hydration helpers to keep the pre-transition class snapshot intact even
when it is empty.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 55e6ffda-3f5e-4262-ba9c-856d06b248c2

📥 Commits

Reviewing files that changed from the base of the PR and between e896551 and 8d3774c.

📒 Files selected for processing (2)
  • packages/runtime-core/__tests__/hydration.spec.ts
  • packages/runtime-core/src/hydration.ts
🛑 Comments failed to post (1)
packages/runtime-core/src/hydration.ts (1)

404-406: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve empty pre-transition classes when checking hydration mismatch.

Line 406 only caches truthy class values, and Line 800 only reads truthy cached values. For <Transition appear> with a class prop that hydrates from class="" or no server class, beforeEnter() can add temporary transition classes before propHasMismatch(), producing a false class mismatch.

Proposed fix
         if (needCallTransitionHooks) {
           const cls = content.getAttribute('class')
-          if (cls) content.$cls = cls
+          if (props && 'class' in props) content.$cls = cls || ''
           transition!.beforeEnter(content)
         }
-    if (el.$cls) {
+    if ('$cls' in el) {
       actual = el.$cls
       delete el.$cls
     } else {

Also applies to: 800-804

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/runtime-core/src/hydration.ts` around lines 404 - 406, The hydration
mismatch check is skipping empty pre-transition class state because hydration.ts
only caches and reads truthy class values in the Transition flow. Update the
logic around content.$cls and the later propHasMismatch() class comparison so
empty string / missing server class is preserved explicitly for
Transition.appear, allowing beforeEnter() temporary classes to be excluded from
mismatch detection. Use the existing hydration transition hooks paths and the
class caching/reading logic in the relevant hydration helpers to keep the
pre-transition class snapshot intact even when it is empty.

@edison1105

Copy link
Copy Markdown
Member Author

/ecosystem-ci run

@vue-bot

vue-bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

📝 Ran ecosystem CI: Open

suite result latest scheduled
language-tools success success
radix-vue failure failure
quasar success success
nuxt success success
pinia success success
vue-i18n success success
vueuse success success
vant success success
vite-plugin-vue success failure
vue-macros success success
vuetify success failure
primevue success success
test-utils success success
vitepress success failure
vue-simple-compiler success failure
router success success

@vuejs vuejs deleted a comment from edison1105 Jun 25, 2026
@edison1105 edison1105 merged commit 164af63 into main Jun 25, 2026
16 checks passed
@edison1105 edison1105 deleted the edison/fix/12782 branch June 25, 2026 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🍰 p2-nice-to-have Priority 2: this is not breaking anything but nice to have it addressed. ready to merge The PR is ready to be merged. scope:hydration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

data-allow-mismatch does not suppress mismatch caused by v-if

3 participants