Skip to content
This repository was archived by the owner on Apr 6, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
7 changes: 3 additions & 4 deletions packages/nuxt/src/app/components/layout.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { defineComponent, isRef, Ref, Transition } from 'vue'
import { _wrapIf } from './utils'
import { useRoute } from '#app'
import { useAppConfig, useRoute } from '#app'
// @ts-ignore
import layouts from '#build/layouts'

const defaultLayoutTransition = { name: 'layout', mode: 'out-in' }

export default defineComponent({
props: {
name: {
Expand All @@ -15,6 +13,7 @@ export default defineComponent({
},
setup (props, context) {
const route = useRoute()
const appConfig = useAppConfig()

return () => {
const layout = (isRef(props.name) ? props.name.value : props.name) ?? route.meta.layout as string ?? 'default'
Expand All @@ -25,7 +24,7 @@ export default defineComponent({
}

// We avoid rendering layout transition if there is no layout to render
return _wrapIf(Transition, hasLayout && (route.meta.layoutTransition ?? defaultLayoutTransition),
return _wrapIf(Transition, hasLayout && (route.meta.layoutTransition ?? appConfig.nuxt.layoutTransition),
_wrapIf(layouts[layout], hasLayout, context.slots)
).default()
}
Expand Down
6 changes: 5 additions & 1 deletion packages/nuxt/src/core/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,17 @@ export const appConfigTemplate: NuxtTemplate = {
filename: 'app.config.mjs',
write: true,
getContents: ({ app, nuxt }) => {
const nuxtKeysToOmit = ['baseURL', 'buildAssetsDir', 'assetsPath', 'cdnURL']
return `
import defu from 'defu'

const inlineConfig = ${JSON.stringify(nuxt.options.appConfig, null, 2)}
const nuxtConfig = {
nuxt: ${JSON.stringify({ ...nuxt.options.app, ...Object.fromEntries(nuxtKeysToOmit.map(k => [k])) }, null, 2)},
}

${app.configs.map((id: string, index: number) => `import ${`cfg${index}`} from ${JSON.stringify(id)}`).join('\n')}
export default defu(${app.configs.map((_id: string, index: number) => `cfg${index}`).concat(['inlineConfig']).join(', ')})
export default defu(${app.configs.map((_id: string, index: number) => `cfg${index}`).concat(['inlineConfig', 'nuxtConfig']).join(', ')})
`
}
}
Expand Down
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
8 changes: 3 additions & 5 deletions packages/nuxt/src/head/runtime/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { computed, getCurrentInstance, markRaw } from 'vue'
import * as Components from './components'
import { useHead } from './composables'
import { defineNuxtPlugin, useNuxtApp } from '#app'
// @ts-ignore
import metaConfig from '#build/meta.config.mjs'
import { defineNuxtPlugin, useAppConfig, useNuxtApp } from '#app'

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

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

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

nuxtApp.vueApp.mixin(metaMixin)

Expand Down
11 changes: 5 additions & 6 deletions packages/nuxt/src/pages/runtime/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { computed, DefineComponent, defineComponent, h, inject, provide, reactiv
import { RouteLocation, RouteLocationNormalized, RouteLocationNormalizedLoaded, RouterView } from 'vue-router'

import { generateRouteKey, RouterViewSlotProps, wrapInKeepAlive } from './utils'
import { useNuxtApp } from '#app'
import { useAppConfig, useNuxtApp } from '#app'
import { _wrapIf } from '#app/components/utils'

const isNestedKey = Symbol('isNested')
Expand All @@ -24,6 +24,7 @@ export default defineComponent({
},
setup (props, { attrs }) {
const nuxtApp = useNuxtApp()
const appConfig = useAppConfig()

const isNested = inject(isNestedKey, false)
provide(isNestedKey, true)
Expand All @@ -35,9 +36,9 @@ export default defineComponent({

const key = generateRouteKey(props.pageKey, routeProps)

return _wrapIf(Transition, routeProps.route.meta.pageTransition ?? defaultPageTransition,
wrapInKeepAlive(routeProps.route.meta.keepalive, isNested && nuxtApp.isHydrating
// Include route children in parent suspense
return _wrapIf(Transition, routeProps.route.meta.pageTransition ?? appConfig.nuxt.pageTransition,
wrapInKeepAlive(routeProps.route.meta.keepalive ?? appConfig.nuxt.keepalive, isNested && nuxtApp.isHydrating
// Include route children in parent suspense
? h(Component, { key, routeProps, pageKey: key } as {})
: h(Suspense, {
onPending: () => nuxtApp.callHook('page:start', routeProps.Component),
Expand All @@ -55,8 +56,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
17 changes: 14 additions & 3 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,13 @@ export interface AppConfigInput extends Record<string, any> {
nitro?: never
}

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

export interface AppConfig {
nuxt: NuxtAppConfig
Comment thread
pi0 marked this conversation as resolved.
Outdated
}
6 changes: 6 additions & 0 deletions test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,12 @@ describe('app config', () => {
const html = await $fetch('/app-config')

const expectedAppConfig = {
nuxt: {
head: { meta: [], link: [], style: [], script: [], noscript: [], charset: 'utf-8', viewport: 'width=1024, initial-scale=1' },
layoutTransition: { name: 'layout', mode: 'out-in' },
pageTransition: { name: 'page', mode: 'out-in' },
keepalive: false
},
fromNuxtConfig: true,
nested: {
val: 2
Expand Down