refactor(hmr): simplify hmr force update check
This commit is contained in:
parent
8f2a7489b7
commit
e76ed4c269
@ -71,10 +71,6 @@ export interface ComponentInternalOptions {
|
||||
* @internal
|
||||
*/
|
||||
__hmrId?: string
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
__hmrUpdated?: boolean
|
||||
/**
|
||||
* This one should be exposed so that devtools can make use of it
|
||||
*/
|
||||
@ -325,12 +321,6 @@ export interface ComponentInternalInstance {
|
||||
* @internal
|
||||
*/
|
||||
[LifecycleHooks.ERROR_CAPTURED]: LifecycleHook
|
||||
|
||||
/**
|
||||
* hmr marker (dev only)
|
||||
* @internal
|
||||
*/
|
||||
hmrUpdated?: boolean
|
||||
}
|
||||
|
||||
const emptyAppContext = createAppContext()
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
import { handleError, ErrorCodes } from './errorHandling'
|
||||
import { PatchFlags, ShapeFlags, isOn } from '@vue/shared'
|
||||
import { warn } from './warning'
|
||||
import { isHmrUpdating } from './hmr'
|
||||
|
||||
// mark the current rendering instance for asset resolution (e.g.
|
||||
// resolveComponent, resolveDirective) during render
|
||||
@ -247,13 +248,8 @@ export function shouldUpdateComponent(
|
||||
// Parent component's render function was hot-updated. Since this may have
|
||||
// caused the child component's slots content to have changed, we need to
|
||||
// force the child to update as well.
|
||||
if (__DEV__ && (prevChildren || nextChildren) && parentComponent) {
|
||||
let parent: ComponentInternalInstance | null = parentComponent
|
||||
do {
|
||||
if (parent.hmrUpdated) {
|
||||
return true
|
||||
}
|
||||
} while ((parent = parent.parent))
|
||||
if (__DEV__ && (prevChildren || nextChildren) && isHmrUpdating) {
|
||||
return true
|
||||
}
|
||||
|
||||
// force child update for runtime directive or transition on component vnode.
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
import { warn } from './warning'
|
||||
import { isKeepAlive } from './components/KeepAlive'
|
||||
import { withCtx } from './helpers/withRenderContext'
|
||||
import { queuePostFlushCb } from './scheduler'
|
||||
import { isHmrUpdating } from './hmr'
|
||||
|
||||
export type Slot = (...args: any[]) => VNode[]
|
||||
|
||||
@ -125,14 +125,10 @@ export const updateSlots = (
|
||||
if (vnode.shapeFlag & ShapeFlags.SLOTS_CHILDREN) {
|
||||
if ((children as RawSlots)._ === 1) {
|
||||
// compiled slots.
|
||||
if (__DEV__ && instance.parent && instance.parent.hmrUpdated) {
|
||||
if (__DEV__ && isHmrUpdating) {
|
||||
// Parent was HMR updated so slot content may have changed.
|
||||
// force update slots and mark instance for hmr as well
|
||||
extend(slots, children as Slots)
|
||||
instance.hmrUpdated = true
|
||||
queuePostFlushCb(() => {
|
||||
instance.hmrUpdated = false
|
||||
})
|
||||
} else if (
|
||||
// bail on dynamic slots (v-if, v-for, reference of scope variables)
|
||||
!(vnode.patchFlag & PatchFlags.DYNAMIC_SLOTS)
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
import {
|
||||
Component,
|
||||
ComponentInternalInstance,
|
||||
ComponentOptions,
|
||||
InternalRenderFunction
|
||||
@ -7,6 +8,10 @@ import {
|
||||
import { queueJob, queuePostFlushCb } from './scheduler'
|
||||
import { extend } from '@vue/shared'
|
||||
|
||||
export let isHmrUpdating = false
|
||||
|
||||
export const hmrDirtyComponents = new Set<Component>()
|
||||
|
||||
export interface HMRRuntime {
|
||||
createRecord: typeof createRecord
|
||||
rerender: typeof rerender
|
||||
@ -72,9 +77,9 @@ function rerender(id: string, newRender?: Function) {
|
||||
}
|
||||
instance.renderCache = []
|
||||
// this flag forces child components with slot content to update
|
||||
instance.hmrUpdated = true
|
||||
isHmrUpdating = true
|
||||
instance.update()
|
||||
instance.hmrUpdated = false
|
||||
isHmrUpdating = false
|
||||
})
|
||||
}
|
||||
|
||||
@ -85,7 +90,7 @@ function reload(id: string, newComp: ComponentOptions) {
|
||||
// updates
|
||||
Array.from(record).forEach(instance => {
|
||||
const comp = instance.type
|
||||
if (!comp.__hmrUpdated) {
|
||||
if (!hmrDirtyComponents.has(comp)) {
|
||||
// 1. Update existing comp definition to match new one
|
||||
extend(comp, newComp)
|
||||
for (const key in comp) {
|
||||
@ -95,10 +100,10 @@ function reload(id: string, newComp: ComponentOptions) {
|
||||
}
|
||||
// 2. Mark component dirty. This forces the renderer to replace the component
|
||||
// on patch.
|
||||
comp.__hmrUpdated = true
|
||||
hmrDirtyComponents.add(comp)
|
||||
// 3. Make sure to unmark the component after the reload.
|
||||
queuePostFlushCb(() => {
|
||||
comp.__hmrUpdated = false
|
||||
hmrDirtyComponents.delete(comp)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ import {
|
||||
} from './components/Suspense'
|
||||
import { TeleportImpl } from './components/Teleport'
|
||||
import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
|
||||
import { registerHMR, unregisterHMR } from './hmr'
|
||||
import { registerHMR, unregisterHMR, isHmrUpdating } from './hmr'
|
||||
import {
|
||||
ErrorCodes,
|
||||
callWithErrorHandling,
|
||||
@ -791,18 +791,11 @@ function baseCreateRenderer(
|
||||
invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate')
|
||||
}
|
||||
|
||||
// check if any component of the parent chain has `hmrUpdated`
|
||||
if (__DEV__ && parentComponent) {
|
||||
let parent: ComponentInternalInstance | null = parentComponent
|
||||
do {
|
||||
if (parent.hmrUpdated) {
|
||||
// HMR updated, force full diff
|
||||
patchFlag = 0
|
||||
optimized = false
|
||||
dynamicChildren = null
|
||||
break
|
||||
}
|
||||
} while ((parent = parent.parent))
|
||||
if (__DEV__ && isHmrUpdating) {
|
||||
// HMR updated, force full diff
|
||||
patchFlag = 0
|
||||
optimized = false
|
||||
dynamicChildren = null
|
||||
}
|
||||
|
||||
if (patchFlag > 0) {
|
||||
@ -1025,7 +1018,7 @@ function baseCreateRenderer(
|
||||
optimized = true
|
||||
}
|
||||
|
||||
if (__DEV__ && parentComponent && parentComponent.hmrUpdated) {
|
||||
if (__DEV__ && isHmrUpdating) {
|
||||
// HMR updated, force full diff
|
||||
patchFlag = 0
|
||||
optimized = false
|
||||
|
@ -32,6 +32,7 @@ import { TeleportImpl, isTeleport } from './components/Teleport'
|
||||
import { currentRenderingInstance } from './componentRenderUtils'
|
||||
import { RendererNode, RendererElement } from './renderer'
|
||||
import { NULL_DYNAMIC_COMPONENT } from './helpers/resolveAssets'
|
||||
import { hmrDirtyComponents } from './hmr'
|
||||
|
||||
export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {
|
||||
__isFragment: true
|
||||
@ -236,7 +237,7 @@ export function isSameVNodeType(n1: VNode, n2: VNode): boolean {
|
||||
if (
|
||||
__DEV__ &&
|
||||
n2.shapeFlag & ShapeFlags.COMPONENT &&
|
||||
(n2.type as Component).__hmrUpdated
|
||||
hmrDirtyComponents.has(n2.type as Component)
|
||||
) {
|
||||
// HMR only: if the component has been hot-updated, force a reload.
|
||||
return false
|
||||
|
Loading…
Reference in New Issue
Block a user