Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

Commit

Permalink
feat(nuxt): config options for default keepalive, page & layout trans…
Browse files Browse the repository at this point in the history
…itions (#5859)
  • Loading branch information
danielroe authored Aug 23, 2022
1 parent fd94351 commit fc82b3b
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 20 deletions.
4 changes: 4 additions & 0 deletions docs/content/2.guide/3.directory-structure/10.pages.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).

You can set a default value for this property [in your `nuxt.config`](/api/configuration/nuxt.config#keepalive).

#### `key`

[See above](#child-route-keys).
Expand All @@ -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 set default values for these properties [in your `nuxt.config`](/api/configuration/nuxt.config#layouttransition).

#### `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.
Expand Down
4 changes: 2 additions & 2 deletions packages/nuxt/src/app/components/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { _wrapIf } from './utils'
import { useRoute } from '#app'
// @ts-ignore
import layouts from '#build/layouts'

const defaultLayoutTransition = { name: 'layout', mode: 'out-in' }
// @ts-ignore
import { appLayoutTransition as defaultLayoutTransition } from '#build/nuxt.config.mjs'

export default defineComponent({
props: {
Expand Down
9 changes: 9 additions & 0 deletions packages/nuxt/src/core/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { isAbsolute, join, relative } from 'pathe'
import { resolveSchema, generateTypes } from 'untyped'
import escapeRE from 'escape-string-regexp'
import { hash } from 'ohash'
import { camelCase } from 'scule'

export interface TemplateContext {
nuxt: Nuxt
Expand Down Expand Up @@ -242,3 +243,11 @@ export const publicPathTemplate: NuxtTemplate = {
].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')
}
}
8 changes: 1 addition & 7 deletions packages/nuxt/src/head/module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { resolve } from 'pathe'
import { addPlugin, addTemplate, defineNuxtModule } from '@nuxt/kit'
import { addPlugin, defineNuxtModule } from '@nuxt/kit'
import { distDir } from '../dirs'

export default defineNuxtModule({
Expand All @@ -15,12 +15,6 @@ export default defineNuxtModule({
// Add #head alias
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
addPlugin({ src: resolve(runtimeDir, 'plugin') })

Expand Down
6 changes: 3 additions & 3 deletions packages/nuxt/src/head/runtime/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import * as Components from './components'
import { useHead } from './composables'
import { defineNuxtPlugin, useNuxtApp } from '#app'
// @ts-ignore
import metaConfig from '#build/meta.config.mjs'
import { appHead } from '#build/nuxt.config.mjs'

type MetaComponents = typeof Components
declare module 'vue' {
export interface GlobalComponents extends MetaComponents {}
export interface GlobalComponents extends MetaComponents { }
}

const metaMixin = {
Expand All @@ -28,7 +28,7 @@ const metaMixin = {
}

export default defineNuxtPlugin((nuxtApp) => {
useHead(markRaw({ title: '', ...metaConfig.globalMeta }))
useHead(markRaw({ title: '', ...appHead }))

nuxtApp.vueApp.mixin(metaMixin)

Expand Down
8 changes: 4 additions & 4 deletions packages/nuxt/src/pages/runtime/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import type { RouteLocation } from 'vue-router'
import { generateRouteKey, RouterViewSlotProps, wrapInKeepAlive } from './utils'
import { useNuxtApp } from '#app'
import { _wrapIf } from '#app/components/utils'
// @ts-ignore
import { appPageTransition as defaultPageTransition, appKeepalive as defaultKeepaliveConfig } from '#build/nuxt.config.mjs'

const isNestedKey = Symbol('isNested')

Expand Down Expand Up @@ -39,8 +41,8 @@ export default defineComponent({
const transitionProps = routeProps.route.meta.pageTransition ?? defaultPageTransition

return _wrapIf(Transition, transitionProps,
wrapInKeepAlive(routeProps.route.meta.keepalive, isNested && nuxtApp.isHydrating
// Include route children in parent suspense
wrapInKeepAlive(routeProps.route.meta.keepalive ?? defaultKeepaliveConfig, isNested && nuxtApp.isHydrating
// Include route children in parent suspense
? h(Component, { key, routeProps, pageKey: key, hasTransition: !!transitionProps } as {})
: h(Suspense, {
onPending: () => nuxtApp.callHook('page:start', routeProps.Component),
Expand All @@ -58,8 +60,6 @@ export default defineComponent({
[key: string]: any
}>

const defaultPageTransition = { name: 'page', mode: 'out-in' }

const Component = defineComponent({
// TODO: Type props
// eslint-disable-next-line vue/require-prop-types
Expand Down
34 changes: 32 additions & 2 deletions packages/schema/src/config/_app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export default {
* }
* }
* ```
* @type {typeof import('../src/types/meta').MetaObject}
* @type {typeof import('../src/types/config').NuxtAppConfig['head']}
* @version 3
*/
head: {
Expand All @@ -123,7 +123,37 @@ export default {

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.
Expand Down
13 changes: 11 additions & 2 deletions packages/schema/src/types/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { KeepAliveProps, TransitionProps } from 'vue'
import { ConfigSchema } from '../../schema/config'
import type { UserConfig as ViteUserConfig } from 'vite'
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

Expand All @@ -13,8 +15,8 @@ export interface NuxtConfig extends DeepPartial<Omit<ConfigSchema, 'vite'>> {

// TODO: Expose ConfigLayer<T> from c12
interface ConfigLayer<T> {
config: T;
cwd: string;
config: T
cwd: string
configFile: string
}
export type NuxtConfigLayer = ConfigLayer<NuxtConfig & {
Expand Down Expand Up @@ -71,4 +73,11 @@ export interface AppConfigInput extends Record<string, any> {
nitro?: never
}

export interface NuxtAppConfig {
head: MetaObject
layoutTransition: boolean | TransitionProps
pageTransition: boolean | TransitionProps
keepalive: boolean | KeepAliveProps
}

export interface AppConfig { }

0 comments on commit fc82b3b

Please sign in to comment.