fix(hmr): avoid hydration for hmr updating (#12262)

close #7706
close #8170
This commit is contained in:
edison 2025-05-13 22:15:50 +08:00 committed by GitHub
parent f7dad6da2f
commit 9c4dbbc518
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 4 deletions

View File

@ -32,10 +32,13 @@ import {
withCtx,
withDirectives,
} from '@vue/runtime-dom'
import type { HMRRuntime } from '../src/hmr'
import { type SSRContext, renderToString } from '@vue/server-renderer'
import { PatchFlags, normalizeStyle } from '@vue/shared'
import { vShowOriginalDisplay } from '../../runtime-dom/src/directives/vShow'
import { expect } from 'vitest'
declare var __VUE_HMR_RUNTIME__: HMRRuntime
const { createRecord, reload } = __VUE_HMR_RUNTIME__
function mountWithHydration(html: string, render: () => any) {
const container = document.createElement('div')
@ -1843,6 +1846,40 @@ describe('SSR hydration', () => {
}
})
test('hmr reload child wrapped in KeepAlive', async () => {
const id = 'child-reload'
const Child = {
__hmrId: id,
template: `<div>foo</div>`,
}
createRecord(id, Child)
const appId = 'test-app-id'
const App = {
__hmrId: appId,
components: { Child },
template: `
<div>
<KeepAlive>
<Child />
</KeepAlive>
</div>
`,
}
const root = document.createElement('div')
root.innerHTML = await renderToString(h(App))
createSSRApp(App).mount(root)
expect(root.innerHTML).toBe('<div><div>foo</div></div>')
reload(id, {
__hmrId: id,
template: `<div>bar</div>`,
})
await nextTick()
expect(root.innerHTML).toBe('<div><div>bar</div></div>')
})
describe('mismatch handling', () => {
test('text node', () => {
const { container } = mountWithHydration(`foo`, () => 'bar')

View File

@ -1208,12 +1208,12 @@ function baseCreateRenderer(
}
}
// setup() is async. This component relies on async logic to be resolved
// before proceeding
if (__FEATURE_SUSPENSE__ && instance.asyncDep) {
// avoid hydration for hmr updating
if (__DEV__ && isHmrUpdating) initialVNode.el = null
// setup() is async. This component relies on async logic to be resolved
// before proceeding
if (__FEATURE_SUSPENSE__ && instance.asyncDep) {
parentSuspense &&
parentSuspense.registerDep(instance, setupRenderEffect, optimized)