Skip to content

Commit 342e8bb

Browse files
authored
refactor(runtime-vapor): improve interop-path treeshaking by isolating interop state (#14424)
1 parent 74d08c8 commit 342e8bb

File tree

6 files changed

+30
-13
lines changed

6 files changed

+30
-13
lines changed

packages/runtime-vapor/src/apiCreateDynamicComponent.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
import { advanceHydrationNode, isHydrating } from './dom/hydration'
1919
import { DynamicFragment, type VaporFragment } from './fragment'
2020
import type { KeepAliveInstance } from './components/KeepAlive'
21+
import { isInteropEnabled } from './vdominteropState'
2122

2223
export function createDynamicComponent(
2324
getter: () => any,
@@ -45,7 +46,7 @@ export function createDynamicComponent(
4546
if (isBlock(value)) return value
4647

4748
// Handles VNodes passed from VDOM components (e.g., `h(VaporComp)` from slots)
48-
if (appContext.vapor && isVNode(value)) {
49+
if (isInteropEnabled && appContext.vapor && isVNode(value)) {
4950
if (isKeepAlive(currentInstance)) {
5051
const frag = (
5152
currentInstance as KeepAliveInstance

packages/runtime-vapor/src/component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ import type {
122122
import { DynamicFragment, isFragment } from './fragment'
123123
import type { VaporElement } from './apiDefineCustomElement'
124124
import { parentSuspense, setParentSuspense } from './components/Suspense'
125+
import { isInteropEnabled } from './vdominteropState'
125126

126127
export { currentInstance } from '@vue/runtime-dom'
127128

@@ -292,7 +293,7 @@ export function createComponent(
292293
}
293294

294295
// vdom interop enabled and component is not an explicit vapor component
295-
if (appContext.vapor && !component.__vapor) {
296+
if (isInteropEnabled && appContext.vapor && !component.__vapor) {
296297
const frag = appContext.vapor.vdomMount(
297298
component as any,
298299
currentInstance as any,

packages/runtime-vapor/src/componentSlots.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
} from './fragment'
2828
import { createElement } from './dom/node'
2929
import { setDynamicProps } from './dom/prop'
30+
import { isInteropEnabled } from './vdominteropState'
3031

3132
/**
3233
* Flag to indicate if we are executing a once slot.
@@ -195,7 +196,7 @@ export function createSlot(
195196
: EMPTY_OBJ
196197

197198
let fragment: SlotFragment
198-
if (isRef(rawSlots._)) {
199+
if (isRef(rawSlots._) && isInteropEnabled) {
199200
if (isHydrating) locateHydrationNode()
200201
fragment = instance.appContext.vapor!.vdomSlot(
201202
rawSlots._,

packages/runtime-vapor/src/components/KeepAlive.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
import { createElement } from '../dom/node'
4040
import { type VaporFragment, isDynamicFragment, isFragment } from '../fragment'
4141
import type { EffectScope } from '@vue/reactivity'
42+
import { isInteropEnabled } from '../vdominteropState'
4243

4344
export interface VaporKeepAliveContext {
4445
processShapeFlag(block: Block): boolean
@@ -154,7 +155,7 @@ const VaporKeepAliveImpl = defineVaporComponent({
154155
keepAliveInstance.ctx = {
155156
getStorageContainer: () => storageContainer,
156157
getCachedComponent: (comp, key) => {
157-
if (isVNode(comp)) {
158+
if (isInteropEnabled && isVNode(comp)) {
158159
return cache.get(resolveKey(comp.type, comp.key, currentBranchKey))
159160
}
160161
return cache.get(resolveKey(comp, key, currentBranchKey))
@@ -219,7 +220,7 @@ const VaporKeepAliveImpl = defineVaporComponent({
219220
const [innerBlock, interop] = getInnerBlock(block)
220221
if (!innerBlock || !shouldCache(innerBlock!, props, interop)) return false
221222

222-
if (interop) {
223+
if (interop && isInteropEnabled) {
223224
const cacheKey = getCacheKey(innerBlock, true, currentBranchKey)
224225
if (cache.has(cacheKey)) {
225226
innerBlock.vnode!.shapeFlag! |= ShapeFlags.COMPONENT_KEPT_ALIVE
@@ -228,9 +229,11 @@ const VaporKeepAliveImpl = defineVaporComponent({
228229
} else {
229230
const cacheKey = getCacheKey(innerBlock, false, currentBranchKey)
230231
if (cache.has(cacheKey)) {
231-
innerBlock!.shapeFlag! |= ShapeFlags.COMPONENT_KEPT_ALIVE
232+
;(innerBlock as VaporComponentInstance)!.shapeFlag! |=
233+
ShapeFlags.COMPONENT_KEPT_ALIVE
232234
}
233-
innerBlock!.shapeFlag! |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
235+
;(innerBlock as VaporComponentInstance)!.shapeFlag! |=
236+
ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
234237
}
235238
return true
236239
}
@@ -352,7 +355,7 @@ const shouldCache = (
352355
) => {
353356
const isAsync = !interop && isAsyncWrapper(block as GenericComponentInstance)
354357
const type = (
355-
interop
358+
interop && isInteropEnabled
356359
? (block as VaporFragment).vnode!.type
357360
: (block as GenericComponentInstance).type
358361
) as GenericComponent & AsyncComponentInternalOptions
@@ -376,7 +379,7 @@ const resetCachedShapeFlag = (
376379
) => {
377380
if (isVaporComponent(cached)) {
378381
resetShapeFlag(cached)
379-
} else {
382+
} else if (isInteropEnabled) {
380383
resetShapeFlag(cached.vnode)
381384
}
382385
}
@@ -405,7 +408,7 @@ function getCacheKey(
405408
interop: boolean,
406409
branchKey?: any,
407410
): CacheKey {
408-
if (interop) {
411+
if (interop && isInteropEnabled) {
409412
const frag = block as VaporFragment
410413
return resolveKey(
411414
frag.vnode!.type,
@@ -420,7 +423,7 @@ function getCacheKey(
420423
function getInnerBlock(block: Block): InnerBlockResult {
421424
if (isVaporComponent(block)) {
422425
return [block, false]
423-
} else if (isInteropFragment(block)) {
426+
} else if (isInteropEnabled && isInteropFragment(block)) {
424427
return [block, true]
425428
} else if (isFragment(block)) {
426429
return getInnerBlock(block.nodes)
@@ -434,12 +437,14 @@ function isInteropFragment(block: Block): block is VaporFragment {
434437

435438
function getInstanceFromCache(
436439
cached: VaporComponentInstance | VaporFragment,
437-
): GenericComponentInstance {
440+
): GenericComponentInstance | undefined {
438441
if (isVaporComponent(cached)) {
439442
return cached
440443
}
441444
// vdom interop
442-
return cached.vnode!.component as GenericComponentInstance
445+
if (isInteropEnabled) {
446+
return cached.vnode!.component as GenericComponentInstance
447+
}
443448
}
444449

445450
export function activate(

packages/runtime-vapor/src/vdomInterop.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ import {
9191
} from './fragment'
9292
import type { NodeRef } from './apiTemplateRef'
9393
import { setTransitionHooks as setVaporTransitionHooks } from './components/Transition'
94+
import { setInteropEnabled } from './vdominteropState'
9495
import {
9596
type KeepAliveInstance,
9697
activate,
@@ -794,6 +795,7 @@ function renderVDOMSlot(
794795
}
795796

796797
export const vaporInteropPlugin: Plugin = app => {
798+
setInteropEnabled()
797799
const internals = ensureRenderer().internals
798800
app._context.vapor = extend(vaporInteropImpl, {
799801
vdomMount: createVDOMComponent.bind(null, internals),
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// if vdom interop plugin is not installed, isInteropEnabled will be false
2+
// the interop code path will be tree-shaken out by bundlers
3+
export let isInteropEnabled = false
4+
5+
export function setInteropEnabled(): void {
6+
isInteropEnabled = true
7+
}

0 commit comments

Comments
 (0)