mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-30 23:32:38 +00:00
perf(nuxt): enable Transition
component only on client side (#30720)
This commit is contained in:
parent
c6056bd07d
commit
e96a96dbd9
@ -1,12 +1,12 @@
|
|||||||
import type { DefineComponent, MaybeRef, VNode } from 'vue'
|
import type { DefineComponent, MaybeRef, VNode } from 'vue'
|
||||||
import { Suspense, Transition, computed, defineComponent, h, inject, mergeProps, nextTick, onMounted, provide, ref, unref } from 'vue'
|
import { Suspense, computed, defineComponent, h, inject, mergeProps, nextTick, onMounted, provide, ref, unref } from 'vue'
|
||||||
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
||||||
|
|
||||||
import type { PageMeta } from '../../pages/runtime/composables'
|
import type { PageMeta } from '../../pages/runtime/composables'
|
||||||
|
|
||||||
import { useRoute, useRouter } from '../composables/router'
|
import { useRoute, useRouter } from '../composables/router'
|
||||||
import { useNuxtApp } from '../nuxt'
|
import { useNuxtApp } from '../nuxt'
|
||||||
import { _wrapIf } from './utils'
|
import { _wrapInTransition } from './utils'
|
||||||
import { LayoutMetaSymbol, PageRouteSymbol } from './injections'
|
import { LayoutMetaSymbol, PageRouteSymbol } from './injections'
|
||||||
|
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
@ -80,7 +80,7 @@ export default defineComponent({
|
|||||||
const transitionProps = route.meta.layoutTransition ?? defaultLayoutTransition
|
const transitionProps = route.meta.layoutTransition ?? defaultLayoutTransition
|
||||||
|
|
||||||
// We avoid rendering layout transition if there is no layout to render
|
// We avoid rendering layout transition if there is no layout to render
|
||||||
return _wrapIf(Transition, hasLayout && transitionProps, {
|
return _wrapInTransition(hasLayout && transitionProps, {
|
||||||
default: () => h(Suspense, { suspensible: true, onResolve: () => { nextTick(done) } }, {
|
default: () => h(Suspense, { suspensible: true, onResolve: () => { nextTick(done) } }, {
|
||||||
default: () => h(
|
default: () => h(
|
||||||
LayoutProvider,
|
LayoutProvider,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createStaticVNode, h } from 'vue'
|
import { Transition, createStaticVNode, h } from 'vue'
|
||||||
import type { Component, RendererNode, VNode } from 'vue'
|
import type { RendererNode, VNode } from 'vue'
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
import { isString, isPromise, isArray, isObject } from '@vue/shared'
|
import { isString, isPromise, isArray, isObject } from '@vue/shared'
|
||||||
import type { RouteLocationNormalized } from 'vue-router'
|
import type { RouteLocationNormalized } from 'vue-router'
|
||||||
@ -10,9 +10,8 @@ import { START_LOCATION } from '#build/pages'
|
|||||||
* Internal utility
|
* Internal utility
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export const _wrapIf = (component: Component, props: any, slots: any) => {
|
export const _wrapInTransition = (props: any, children: any) => {
|
||||||
props = props === true ? {} : props
|
return { default: () => import.meta.client && props ? h(Transition, props === true ? {} : props, children) : children.default?.() }
|
||||||
return { default: () => props ? h(component, props, slots) : slots.default?.() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ROUTE_KEY_PARENTHESES_RE = /(:\w+)\([^)]+\)/g
|
const ROUTE_KEY_PARENTHESES_RE = /(:\w+)\([^)]+\)/g
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Fragment, Suspense, Transition, defineComponent, h, inject, nextTick, ref, watch } from 'vue'
|
import { Fragment, Suspense, defineComponent, h, inject, nextTick, ref, watch } from 'vue'
|
||||||
import type { KeepAliveProps, TransitionProps, VNode } from 'vue'
|
import type { KeepAliveProps, TransitionProps, VNode } from 'vue'
|
||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
import { defu } from 'defu'
|
import { defu } from 'defu'
|
||||||
@ -9,7 +9,7 @@ import type { RouterViewSlotProps } from './utils'
|
|||||||
import { RouteProvider } from '#app/components/route-provider'
|
import { RouteProvider } from '#app/components/route-provider'
|
||||||
import { useNuxtApp } from '#app/nuxt'
|
import { useNuxtApp } from '#app/nuxt'
|
||||||
import { useRouter } from '#app/composables/router'
|
import { useRouter } from '#app/composables/router'
|
||||||
import { _wrapIf } from '#app/components/utils'
|
import { _wrapInTransition } from '#app/components/utils'
|
||||||
import { LayoutMetaSymbol, PageRouteSymbol } from '#app/components/injections'
|
import { LayoutMetaSymbol, PageRouteSymbol } from '#app/components/injections'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { appKeepalive as defaultKeepaliveConfig, appPageTransition as defaultPageTransition } from '#build/nuxt.config.mjs'
|
import { appKeepalive as defaultKeepaliveConfig, appPageTransition as defaultPageTransition } from '#build/nuxt.config.mjs'
|
||||||
@ -101,8 +101,30 @@ export default defineComponent({
|
|||||||
nuxtApp.callHook('page:loading:end')
|
nuxtApp.callHook('page:loading:end')
|
||||||
pageLoadingEndHookAlreadyCalled = true
|
pageLoadingEndHookAlreadyCalled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
previousPageKey = key
|
previousPageKey = key
|
||||||
|
|
||||||
|
if (import.meta.server) {
|
||||||
|
vnode = h(Suspense, {
|
||||||
|
suspensible: true,
|
||||||
|
}, {
|
||||||
|
default: () => {
|
||||||
|
const providerVNode = h(RouteProvider, {
|
||||||
|
key: key || undefined,
|
||||||
|
vnode: slots.default ? h(Fragment, undefined, slots.default(routeProps)) : routeProps.Component,
|
||||||
|
route: routeProps.route,
|
||||||
|
renderKey: key || undefined,
|
||||||
|
vnodeRef: pageRef,
|
||||||
|
})
|
||||||
|
return providerVNode
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return vnode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client side rendering
|
||||||
|
|
||||||
const hasTransition = !!(props.transition ?? routeProps.route.meta.pageTransition ?? defaultPageTransition)
|
const hasTransition = !!(props.transition ?? routeProps.route.meta.pageTransition ?? defaultPageTransition)
|
||||||
const transitionProps = hasTransition && _mergeTransitionProps([
|
const transitionProps = hasTransition && _mergeTransitionProps([
|
||||||
props.transition,
|
props.transition,
|
||||||
@ -112,7 +134,7 @@ export default defineComponent({
|
|||||||
].filter(Boolean))
|
].filter(Boolean))
|
||||||
|
|
||||||
const keepaliveConfig = props.keepalive ?? routeProps.route.meta.keepalive ?? (defaultKeepaliveConfig as KeepAliveProps)
|
const keepaliveConfig = props.keepalive ?? routeProps.route.meta.keepalive ?? (defaultKeepaliveConfig as KeepAliveProps)
|
||||||
vnode = _wrapIf(Transition, hasTransition && transitionProps,
|
vnode = _wrapInTransition(hasTransition && transitionProps,
|
||||||
wrapInKeepAlive(keepaliveConfig, h(Suspense, {
|
wrapInKeepAlive(keepaliveConfig, h(Suspense, {
|
||||||
suspensible: true,
|
suspensible: true,
|
||||||
onPending: () => nuxtApp.callHook('page:start', routeProps.Component),
|
onPending: () => nuxtApp.callHook('page:start', routeProps.Component),
|
||||||
@ -134,7 +156,7 @@ export default defineComponent({
|
|||||||
trackRootNodes: hasTransition,
|
trackRootNodes: hasTransition,
|
||||||
vnodeRef: pageRef,
|
vnodeRef: pageRef,
|
||||||
})
|
})
|
||||||
if (import.meta.client && keepaliveConfig) {
|
if (keepaliveConfig) {
|
||||||
(providerVNode.type as any).name = (routeProps.Component.type as any).name || (routeProps.Component.type as any).__name || 'RouteProvider'
|
(providerVNode.type as any).name = (routeProps.Component.type as any).name || (routeProps.Component.type as any).__name || 'RouteProvider'
|
||||||
}
|
}
|
||||||
return providerVNode
|
return providerVNode
|
||||||
|
@ -78,7 +78,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
|||||||
const serverDir = join(rootDir, '.output-inline/server')
|
const serverDir = join(rootDir, '.output-inline/server')
|
||||||
|
|
||||||
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
||||||
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"566k"`)
|
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot(`"564k"`)
|
||||||
|
|
||||||
const modules = await analyzeSizes(['node_modules/**/*'], serverDir)
|
const modules = await analyzeSizes(['node_modules/**/*'], serverDir)
|
||||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"92.3k"`)
|
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot(`"92.3k"`)
|
||||||
|
Loading…
Reference in New Issue
Block a user