From 4eee630b3122a10d0baf9b91358cfffa92d6fd81 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 4 Sep 2024 20:22:19 +0800 Subject: [PATCH] fix(build): improve built-in components treeshakability --- .../runtime-core/src/components/KeepAlive.ts | 9 ++-- .../runtime-dom/src/components/Transition.ts | 46 +++++++++++-------- .../src/components/TransitionGroup.ts | 32 +++++++------ 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts index f897f4037..e61c14f34 100644 --- a/packages/runtime-core/src/components/KeepAlive.ts +++ b/packages/runtime-core/src/components/KeepAlive.ts @@ -362,13 +362,16 @@ const KeepAliveImpl: ComponentOptions = { }, } -if (__COMPAT__) { - KeepAliveImpl.__isBuildIn = true +const decorate = (t: typeof KeepAliveImpl) => { + t.__isBuiltIn = true + return t } // export the public type for h/tsx inference // also to avoid inline import() in generated d.ts files -export const KeepAlive = KeepAliveImpl as any as { +export const KeepAlive = (__COMPAT__ + ? /*#__PURE__*/ decorate(KeepAliveImpl) + : KeepAliveImpl) as any as { __isKeepAlive: true new (): { $props: VNodeProps & KeepAliveProps diff --git a/packages/runtime-dom/src/components/Transition.ts b/packages/runtime-dom/src/components/Transition.ts index f549a9318..94cf9b633 100644 --- a/packages/runtime-dom/src/components/Transition.ts +++ b/packages/runtime-dom/src/components/Transition.ts @@ -42,19 +42,6 @@ export interface ElementWithTransition extends HTMLElement { [vtcKey]?: Set } -// DOM Transition is a higher-order-component based on the platform-agnostic -// base Transition component, with DOM-specific logic. -export const Transition: FunctionalComponent = ( - props, - { slots }, -) => h(BaseTransition, resolveTransitionProps(props), slots) - -Transition.displayName = 'Transition' - -if (__COMPAT__) { - Transition.__isBuiltIn = true -} - const DOMTransitionPropsValidators = { name: String, type: String, @@ -74,12 +61,33 @@ const DOMTransitionPropsValidators = { leaveToClass: String, } -export const TransitionPropsValidators: any = (Transition.props = - /*#__PURE__*/ extend( - {}, - BaseTransitionPropsValidators as any, - DOMTransitionPropsValidators, - )) +export const TransitionPropsValidators: any = /*#__PURE__*/ extend( + {}, + BaseTransitionPropsValidators as any, + DOMTransitionPropsValidators, +) + +/** + * Wrap logic that attaches extra properties to Transition in a function + * so that it can be annotated as pure + */ +const decorate = (t: typeof Transition) => { + t.displayName = 'Transition' + t.props = TransitionPropsValidators + if (__COMPAT__) { + t.__isBuiltIn = true + } + return t +} + +/** + * DOM Transition is a higher-order-component based on the platform-agnostic + * base Transition component, with DOM-specific logic. + */ +export const Transition: FunctionalComponent = + /*#__PURE__*/ decorate((props, { slots }) => + h(BaseTransition, resolveTransitionProps(props), slots), + ) /** * #3227 Incoming hooks may be merged into arrays when wrapping Transition diff --git a/packages/runtime-dom/src/components/TransitionGroup.ts b/packages/runtime-dom/src/components/TransitionGroup.ts index 763b7a98b..a596c3df9 100644 --- a/packages/runtime-dom/src/components/TransitionGroup.ts +++ b/packages/runtime-dom/src/components/TransitionGroup.ts @@ -32,12 +32,27 @@ const positionMap = new WeakMap() const newPositionMap = new WeakMap() const moveCbKey = Symbol('_moveCb') const enterCbKey = Symbol('_enterCb') + export type TransitionGroupProps = Omit & { tag?: string moveClass?: string } -const TransitionGroupImpl: ComponentOptions = { +/** + * Wrap logic that modifies TransitionGroup properties in a function + * so that it can be annotated as pure + */ +const decorate = (t: typeof TransitionGroupImpl) => { + // TransitionGroup does not support "mode" so we need to remove it from the + // props declarations, but direct delete operation is considered a side effect + delete t.props.mode + if (__COMPAT__) { + t.__isBuiltIn = true + } + return t +} + +const TransitionGroupImpl: ComponentOptions = /*#__PURE__*/ decorate({ name: 'TransitionGroup', props: /*#__PURE__*/ extend({}, TransitionPropsValidators, { @@ -152,20 +167,7 @@ const TransitionGroupImpl: ComponentOptions = { return createVNode(tag, null, children) } }, -} - -if (__COMPAT__) { - TransitionGroupImpl.__isBuiltIn = true -} - -/** - * TransitionGroup does not support "mode" so we need to remove it from the - * props declarations, but direct delete operation is considered a side effect - * and will make the entire transition feature non-tree-shakeable, so we do it - * in a function and mark the function's invocation as pure. - */ -const removeMode = (props: any) => delete props.mode -/*#__PURE__*/ removeMode(TransitionGroupImpl.props) +}) export const TransitionGroup = TransitionGroupImpl as unknown as { new (): {