feat(nuxt): config options for default keepalive, page & layout transitions (#5859)

This commit is contained in:
Daniel Roe 2022-08-23 15:24:20 +01:00 committed by GitHub
parent fd94351ee9
commit fc82b3b340
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 66 additions and 20 deletions

View File

@ -267,6 +267,8 @@ Of course, you are welcome to define metadata for your own use throughout your a
Nuxt will automatically wrap your page in [the Vue `<KeepAlive>` component](https://vuejs.org/guide/built-ins/keep-alive.html#keepalive) if you set `keepalive: true` in your `definePageMeta`. This might be useful to do, for example, in a parent route that has dynamic child routes, if you want to preserve page state across route changes. You can also set props to be passed to `<KeepAlive>` (see a full list [here](https://vuejs.org/api/built-in-components.html#keepalive)). Nuxt will automatically wrap your page in [the Vue `<KeepAlive>` component](https://vuejs.org/guide/built-ins/keep-alive.html#keepalive) if you set `keepalive: true` in your `definePageMeta`. This might be useful to do, for example, in a parent route that has dynamic child routes, if you want to preserve page state across route changes. You can also set props to be passed to `<KeepAlive>` (see a full list [here](https://vuejs.org/api/built-in-components.html#keepalive)).
You can set a default value for this property [in your `nuxt.config`](/api/configuration/nuxt.config#keepalive).
#### `key` #### `key`
[See above](#child-route-keys). [See above](#child-route-keys).
@ -283,6 +285,8 @@ You can define middleware to apply before loading this page. It will be merged w
You can define transition properties for the `<transition>` component that wraps your pages and layouts, or pass `false` to disable the `<transition>` wrapper for that route. You can see a list of options that can be passed [here](https://vuejs.org/api/built-in-components.html#transition) or read [more about how transitions work](https://vuejs.org/guide/built-ins/transition.html#transition). You can define transition properties for the `<transition>` component that wraps your pages and layouts, or pass `false` to disable the `<transition>` wrapper for that route. You can see a list of options that can be passed [here](https://vuejs.org/api/built-in-components.html#transition) or read [more about how transitions work](https://vuejs.org/guide/built-ins/transition.html#transition).
You can set default values for these properties [in your `nuxt.config`](/api/configuration/nuxt.config#layouttransition).
#### `alias` #### `alias`
You can define page aliases. They allow you to access the same page from different paths. It can be either a string or an array of strings as defined [here](https://router.vuejs.org/guide/essentials/redirect-and-alias.html#alias) on vue-router documentation. You can define page aliases. They allow you to access the same page from different paths. It can be either a string or an array of strings as defined [here](https://router.vuejs.org/guide/essentials/redirect-and-alias.html#alias) on vue-router documentation.

View File

@ -3,8 +3,8 @@ import { _wrapIf } from './utils'
import { useRoute } from '#app' import { useRoute } from '#app'
// @ts-ignore // @ts-ignore
import layouts from '#build/layouts' import layouts from '#build/layouts'
// @ts-ignore
const defaultLayoutTransition = { name: 'layout', mode: 'out-in' } import { appLayoutTransition as defaultLayoutTransition } from '#build/nuxt.config.mjs'
export default defineComponent({ export default defineComponent({
props: { props: {

View File

@ -5,6 +5,7 @@ import { isAbsolute, join, relative } from 'pathe'
import { resolveSchema, generateTypes } from 'untyped' import { resolveSchema, generateTypes } from 'untyped'
import escapeRE from 'escape-string-regexp' import escapeRE from 'escape-string-regexp'
import { hash } from 'ohash' import { hash } from 'ohash'
import { camelCase } from 'scule'
export interface TemplateContext { export interface TemplateContext {
nuxt: Nuxt nuxt: Nuxt
@ -242,3 +243,11 @@ export const publicPathTemplate: NuxtTemplate = {
].filter(Boolean).join('\n') ].filter(Boolean).join('\n')
} }
} }
// Allow direct access to specific exposed nuxt.config
export const nuxtConfigTemplate = {
filename: 'nuxt.config.mjs',
getContents: (ctx: TemplateContext) => {
return Object.entries(ctx.nuxt.options.app).map(([k, v]) => `export const ${camelCase('app-' + k)} = ${JSON.stringify(v)}`).join('\n\n')
}
}

View File

@ -1,5 +1,5 @@
import { resolve } from 'pathe' import { resolve } from 'pathe'
import { addPlugin, addTemplate, defineNuxtModule } from '@nuxt/kit' import { addPlugin, defineNuxtModule } from '@nuxt/kit'
import { distDir } from '../dirs' import { distDir } from '../dirs'
export default defineNuxtModule({ export default defineNuxtModule({
@ -15,12 +15,6 @@ export default defineNuxtModule({
// Add #head alias // Add #head alias
nuxt.options.alias['#head'] = runtimeDir nuxt.options.alias['#head'] = runtimeDir
// Add global meta configuration
addTemplate({
filename: 'meta.config.mjs',
getContents: () => 'export default ' + JSON.stringify({ globalMeta: nuxt.options.app.head })
})
// Add generic plugin // Add generic plugin
addPlugin({ src: resolve(runtimeDir, 'plugin') }) addPlugin({ src: resolve(runtimeDir, 'plugin') })

View File

@ -3,7 +3,7 @@ import * as Components from './components'
import { useHead } from './composables' import { useHead } from './composables'
import { defineNuxtPlugin, useNuxtApp } from '#app' import { defineNuxtPlugin, useNuxtApp } from '#app'
// @ts-ignore // @ts-ignore
import metaConfig from '#build/meta.config.mjs' import { appHead } from '#build/nuxt.config.mjs'
type MetaComponents = typeof Components type MetaComponents = typeof Components
declare module 'vue' { declare module 'vue' {
@ -28,7 +28,7 @@ const metaMixin = {
} }
export default defineNuxtPlugin((nuxtApp) => { export default defineNuxtPlugin((nuxtApp) => {
useHead(markRaw({ title: '', ...metaConfig.globalMeta })) useHead(markRaw({ title: '', ...appHead }))
nuxtApp.vueApp.mixin(metaMixin) nuxtApp.vueApp.mixin(metaMixin)

View File

@ -6,6 +6,8 @@ import type { RouteLocation } from 'vue-router'
import { generateRouteKey, RouterViewSlotProps, wrapInKeepAlive } from './utils' import { generateRouteKey, RouterViewSlotProps, wrapInKeepAlive } from './utils'
import { useNuxtApp } from '#app' import { useNuxtApp } from '#app'
import { _wrapIf } from '#app/components/utils' import { _wrapIf } from '#app/components/utils'
// @ts-ignore
import { appPageTransition as defaultPageTransition, appKeepalive as defaultKeepaliveConfig } from '#build/nuxt.config.mjs'
const isNestedKey = Symbol('isNested') const isNestedKey = Symbol('isNested')
@ -39,7 +41,7 @@ export default defineComponent({
const transitionProps = routeProps.route.meta.pageTransition ?? defaultPageTransition const transitionProps = routeProps.route.meta.pageTransition ?? defaultPageTransition
return _wrapIf(Transition, transitionProps, return _wrapIf(Transition, transitionProps,
wrapInKeepAlive(routeProps.route.meta.keepalive, isNested && nuxtApp.isHydrating wrapInKeepAlive(routeProps.route.meta.keepalive ?? defaultKeepaliveConfig, isNested && nuxtApp.isHydrating
// Include route children in parent suspense // Include route children in parent suspense
? h(Component, { key, routeProps, pageKey: key, hasTransition: !!transitionProps } as {}) ? h(Component, { key, routeProps, pageKey: key, hasTransition: !!transitionProps } as {})
: h(Suspense, { : h(Suspense, {
@ -58,8 +60,6 @@ export default defineComponent({
[key: string]: any [key: string]: any
}> }>
const defaultPageTransition = { name: 'page', mode: 'out-in' }
const Component = defineComponent({ const Component = defineComponent({
// TODO: Type props // TODO: Type props
// eslint-disable-next-line vue/require-prop-types // eslint-disable-next-line vue/require-prop-types

View File

@ -100,7 +100,7 @@ export default {
* } * }
* } * }
* ``` * ```
* @type {typeof import('../src/types/meta').MetaObject} * @type {typeof import('../src/types/config').NuxtAppConfig['head']}
* @version 3 * @version 3
*/ */
head: { head: {
@ -123,7 +123,37 @@ export default {
return resolved return resolved
} }
} },
/**
* Default values for layout transitions.
*
* This can be overridden with `definePageMeta` on an individual page.
* Only JSON-serializable values are allowed.
*
* @see https://vuejs.org/api/built-in-components.html#transition
* @type {typeof import('../src/types/config').NuxtAppConfig['layoutTransition']}
*/
layoutTransition: { name: 'layout', mode: 'out-in' },
/**
* Default values for page transitions.
*
* This can be overridden with `definePageMeta` on an individual page.
* Only JSON-serializable values are allowed.
*
* @see https://vuejs.org/api/built-in-components.html#transition
* @type {typeof import('../src/types/config').NuxtAppConfig['pageTransition']}
*/
pageTransition: { name: 'page', mode: 'out-in' },
/**
* Default values for KeepAlive configuration between pages.
*
* This can be overridden with `definePageMeta` on an individual page.
* Only JSON-serializable values are allowed.
*
* @see https://vuejs.org/api/built-in-components.html#keepalive
* @type {typeof import('../src/types/config').NuxtAppConfig['keepalive']}
*/
keepalive: false,
}, },
/** /**
* The path to an HTML template file for rendering Nuxt responses. * The path to an HTML template file for rendering Nuxt responses.

View File

@ -1,6 +1,8 @@
import type { KeepAliveProps, TransitionProps } from 'vue'
import { ConfigSchema } from '../../schema/config' import { ConfigSchema } from '../../schema/config'
import type { UserConfig as ViteUserConfig } from 'vite' import type { UserConfig as ViteUserConfig } from 'vite'
import type { Options as VuePluginOptions } from '@vitejs/plugin-vue' import type { Options as VuePluginOptions } from '@vitejs/plugin-vue'
import type { MetaObject } from './meta'
type DeepPartial<T> = T extends Function ? T : T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T type DeepPartial<T> = T extends Function ? T : T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T
@ -13,8 +15,8 @@ export interface NuxtConfig extends DeepPartial<Omit<ConfigSchema, 'vite'>> {
// TODO: Expose ConfigLayer<T> from c12 // TODO: Expose ConfigLayer<T> from c12
interface ConfigLayer<T> { interface ConfigLayer<T> {
config: T; config: T
cwd: string; cwd: string
configFile: string configFile: string
} }
export type NuxtConfigLayer = ConfigLayer<NuxtConfig & { export type NuxtConfigLayer = ConfigLayer<NuxtConfig & {
@ -71,4 +73,11 @@ export interface AppConfigInput extends Record<string, any> {
nitro?: never nitro?: never
} }
export interface NuxtAppConfig {
head: MetaObject
layoutTransition: boolean | TransitionProps
pageTransition: boolean | TransitionProps
keepalive: boolean | KeepAliveProps
}
export interface AppConfig { } export interface AppConfig { }