From 5dce316d193109a315834784b4ded3c5e8a19b1d Mon Sep 17 00:00:00 2001 From: daiwei Date: Wed, 5 Mar 2025 10:12:19 +0800 Subject: [PATCH] wip: inject useVaporTransition call for treeshaking --- packages/compiler-vapor/src/generate.ts | 5 ++ packages/compiler-vapor/src/ir/index.ts | 1 + packages/compiler-vapor/src/transform.ts | 1 + packages/compiler-vapor/src/transforms/vIf.ts | 16 +++-- .../compiler-vapor/src/transforms/vSlot.ts | 2 +- packages/runtime-vapor/src/apiCreateApp.ts | 2 - .../src/components/Transition.ts | 58 +++++++++---------- packages/runtime-vapor/src/index.ts | 1 + packages/runtime-vapor/src/vdomInterop.ts | 2 - 9 files changed, 50 insertions(+), 38 deletions(-) diff --git a/packages/compiler-vapor/src/generate.ts b/packages/compiler-vapor/src/generate.ts index 193a0f5da7..64d346d1d5 100644 --- a/packages/compiler-vapor/src/generate.ts +++ b/packages/compiler-vapor/src/generate.ts @@ -129,6 +129,11 @@ export function generate( `const ${setTemplateRefIdent} = ${context.helper('createTemplateRefSetter')}()`, ) } + + if (ir.hasTransition) { + push(NEWLINE, `${context.helper('useVaporTransition')}()`) + } + push(...genBlockContent(ir.block, context, true)) push(INDENT_END, NEWLINE) diff --git a/packages/compiler-vapor/src/ir/index.ts b/packages/compiler-vapor/src/ir/index.ts index 71e896e13f..6c80662a57 100644 --- a/packages/compiler-vapor/src/ir/index.ts +++ b/packages/compiler-vapor/src/ir/index.ts @@ -68,6 +68,7 @@ export interface RootIRNode { directive: Set block: BlockIRNode hasTemplateRef: boolean + hasTransition: boolean } export interface IfIRNode extends BaseIRNode { diff --git a/packages/compiler-vapor/src/transform.ts b/packages/compiler-vapor/src/transform.ts index 76563899d2..788b1889ab 100644 --- a/packages/compiler-vapor/src/transform.ts +++ b/packages/compiler-vapor/src/transform.ts @@ -230,6 +230,7 @@ export function transform( directive: new Set(), block: newBlock(node), hasTemplateRef: false, + hasTransition: false, } const context = new TransformContext(ir, node, options) diff --git a/packages/compiler-vapor/src/transforms/vIf.ts b/packages/compiler-vapor/src/transforms/vIf.ts index 5306cf7057..9151343495 100644 --- a/packages/compiler-vapor/src/transforms/vIf.ts +++ b/packages/compiler-vapor/src/transforms/vIf.ts @@ -134,12 +134,20 @@ export function isInTransition( context: TransformContext, ): boolean { const parentNode = context.parent && context.parent.node - return !!(parentNode && isTransitionNode(parentNode as ElementNode)) + return !!(parentNode && isTransitionNode(parentNode as ElementNode, context)) } -export function isTransitionNode(node: ElementNode): boolean { - return ( +export function isTransitionNode( + node: ElementNode, + context: TransformContext, +): boolean { + const inTransition = node.type === NodeTypes.ELEMENT && (node.tag === 'transition' || node.tag === 'Transition') - ) + + if (inTransition) { + context.ir.hasTransition = true + } + + return inTransition } diff --git a/packages/compiler-vapor/src/transforms/vSlot.ts b/packages/compiler-vapor/src/transforms/vSlot.ts index c1b82e2bc5..d14f91b58c 100644 --- a/packages/compiler-vapor/src/transforms/vSlot.ts +++ b/packages/compiler-vapor/src/transforms/vSlot.ts @@ -74,7 +74,7 @@ function transformComponentSlot( ) let slotKey - if (isTransitionNode(node)) { + if (isTransitionNode(node, context)) { const keyProp = findProp( nonSlotTemplateChildren[0] as ElementNode, 'key', diff --git a/packages/runtime-vapor/src/apiCreateApp.ts b/packages/runtime-vapor/src/apiCreateApp.ts index da09a79a12..8088e1aee6 100644 --- a/packages/runtime-vapor/src/apiCreateApp.ts +++ b/packages/runtime-vapor/src/apiCreateApp.ts @@ -20,13 +20,11 @@ import { import type { RawProps } from './componentProps' import { getGlobalThis } from '@vue/shared' import { optimizePropertyLookup } from './dom/prop' -import { ensureVaporTransition } from './components/Transition' let _createApp: CreateAppFunction const mountApp: AppMountFn = (app, container) => { optimizePropertyLookup() - ensureVaporTransition() // clear content before mounting if (container.nodeType === 1 /* Node.ELEMENT_NODE */) { diff --git a/packages/runtime-vapor/src/components/Transition.ts b/packages/runtime-vapor/src/components/Transition.ts index 44f87023ed..a7f540fa6a 100644 --- a/packages/runtime-vapor/src/components/Transition.ts +++ b/packages/runtime-vapor/src/components/Transition.ts @@ -21,6 +21,7 @@ import { } from '../block' import { isVaporComponent } from '../component' +/*#__NO_SIDE_EFFECTS__*/ export const vaporTransitionImpl: VaporTransitionInterface = { applyTransition: ( props: TransitionProps, @@ -118,31 +119,29 @@ function setTransitionHooks( block: TransitionBlock, hooks: VaporTransitionHooks, ) { - if (!isFragment(block)) { - block.$transition = hooks - } + block.$transition = hooks } export function applyTransitionEnterHooks( block: Block, hooks: VaporTransitionHooks, -): VaporTransitionHooks | undefined { - const child = findElementChild(block) - let enterHooks - if (child) { - const { props, state, delayedLeave } = hooks - enterHooks = resolveTransitionHooks( - child, - props, - state, - currentInstance!, - hooks => (enterHooks = hooks as VaporTransitionHooks), - ) - enterHooks.delayedLeave = delayedLeave - setTransitionHooks(child, enterHooks) - if (isFragment(block)) { - block.$transition = enterHooks - } +): VaporTransitionHooks { + const child = findTransitionBlock(block) + if (!child) return hooks + + const { props, state, delayedLeave } = hooks + let enterHooks = resolveTransitionHooks( + child, + props, + state, + currentInstance!, + hooks => (enterHooks = hooks as VaporTransitionHooks), + ) + enterHooks.delayedLeave = delayedLeave + setTransitionHooks(child, enterHooks) + if (isFragment(block)) { + // also set transition hooks on fragment for reusing during it's updating + setTransitionHooks(block, enterHooks) } return enterHooks } @@ -152,7 +151,7 @@ export function applyTransitionLeaveHooks( enterHooks: VaporTransitionHooks, afterLeaveCb: () => void, ): void { - const leavingBlock = findElementChild(block) + const leavingBlock = findTransitionBlock(block) if (!leavingBlock) return undefined const { props, state } = enterHooks @@ -196,10 +195,10 @@ export function applyTransitionLeaveHooks( } } -const transitionChildCache = new WeakMap() -export function findElementChild(block: Block): TransitionBlock | undefined { - if (transitionChildCache.has(block)) { - return transitionChildCache.get(block) +const transitionBlockCache = new WeakMap() +export function findTransitionBlock(block: Block): TransitionBlock | undefined { + if (transitionBlockCache.has(block)) { + return transitionBlockCache.get(block) } let child: TransitionBlock | undefined @@ -207,12 +206,12 @@ export function findElementChild(block: Block): TransitionBlock | undefined { // transition can only be applied on Element child if (block instanceof Element) child = block } else if (isVaporComponent(block)) { - child = findElementChild(block.block) + child = findTransitionBlock(block.block) } else if (Array.isArray(block)) { child = block[0] as TransitionBlock let hasFound = false for (const c of block) { - const item = findElementChild(c) + const item = findTransitionBlock(c) if (item instanceof Element) { if (__DEV__ && hasFound) { // warn more than one non-comment child @@ -228,7 +227,7 @@ export function findElementChild(block: Block): TransitionBlock | undefined { } } } else if (isFragment(block)) { - child = findElementChild(block.nodes) + child = findTransitionBlock(block.nodes) } if (__DEV__ && !child) { @@ -239,7 +238,8 @@ export function findElementChild(block: Block): TransitionBlock | undefined { } let registered = false -export function ensureVaporTransition(): void { +/*#__NO_SIDE_EFFECTS__*/ +export function useVaporTransition(): void { if (!registered) { registerVaporTransition(vaporTransitionImpl) registered = true diff --git a/packages/runtime-vapor/src/index.ts b/packages/runtime-vapor/src/index.ts index c356727f86..4a9986b43a 100644 --- a/packages/runtime-vapor/src/index.ts +++ b/packages/runtime-vapor/src/index.ts @@ -42,3 +42,4 @@ export { applyDynamicModel, } from './directives/vModel' export { withVaporDirectives } from './directives/custom' +export { useVaporTransition } from './components/Transition' diff --git a/packages/runtime-vapor/src/vdomInterop.ts b/packages/runtime-vapor/src/vdomInterop.ts index efe8223c60..77228fd72a 100644 --- a/packages/runtime-vapor/src/vdomInterop.ts +++ b/packages/runtime-vapor/src/vdomInterop.ts @@ -33,7 +33,6 @@ import type { RawSlots, VaporSlot } from './componentSlots' import { renderEffect } from './renderEffect' import { createTextNode } from './dom/node' import { optimizePropertyLookup } from './dom/prop' -import { ensureVaporTransition } from './components/Transition' // mounting vapor components and slots in vdom const vaporInteropImpl: Omit< @@ -289,7 +288,6 @@ export const vaporInteropPlugin: Plugin = app => { const mount = app.mount app.mount = ((...args) => { optimizePropertyLookup() - ensureVaporTransition() return mount(...args) }) satisfies App['mount'] } -- 2.47.2