feat(nuxt): `app.config` improvements (#6905)

This commit is contained in:
Yaël Guilloux 2022-08-24 18:35:02 +02:00 committed by GitHub
parent a4dfe232f0
commit 1700bf822e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 20 deletions

View File

@ -0,0 +1,20 @@
# `updateAppConfig`
::StabilityEdge
::
Updates [app config](/guide/features/app-config) using deep assignment. Existing (nested) properties will be preserved.
**Usage:**
```js
const appConfig = useAppConfig() // { foo: 'bar' }
const newAppConfig = { foo: 'baz' }
updateAppConfig(newAppConfig)
console.log(appConfig) // { foo: 'baz' }
```
::ReadMore{link="/guide/features/app-config"}

View File

@ -1,5 +1,10 @@
export default defineAppConfig({
foo: 'user',
bar: 'user',
baz: 'base'
baz: 'base',
array: [
'user',
'user',
'user'
]
})

View File

@ -1,4 +1,18 @@
export default defineAppConfig({
bar: 'base',
baz: 'base'
baz: 'base',
array: () => [
'base',
'base',
'base'
],
arrayNested: {
nested: {
array: [
'base',
'base',
'base'
]
}
}
})

View File

@ -4,9 +4,35 @@ import { useNuxtApp } from './nuxt'
// @ts-ignore
import __appConfig from '#build/app.config.mjs'
type DeepPartial<T> = T extends Function ? T : T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T
// Workaround for vite HMR with virtual modules
export const _getAppConfig = () => __appConfig as AppConfig
function deepDelete (obj: any, newObj: any) {
for (const key in obj) {
const val = newObj[key]
if (!(key in newObj)) {
delete (obj as any)[key]
}
if (val !== null && typeof val === 'object') {
deepDelete(obj[key], newObj[key])
}
}
}
function deepAssign (obj: any, newObj: any) {
for (const key in newObj) {
const val = newObj[key]
if (val !== null && typeof val === 'object') {
deepAssign(obj[key], val)
} else {
obj[key] = val
}
}
}
export function useAppConfig (): AppConfig {
const nuxtApp = useNuxtApp()
if (!nuxtApp._appConfig) {
@ -15,28 +41,23 @@ export function useAppConfig (): AppConfig {
return nuxtApp._appConfig
}
/**
* Deep assign the current appConfig with the new one.
*
* Will preserve existing properties.
*/
export function updateAppConfig (appConfig: DeepPartial<AppConfig>) {
const _appConfig = useAppConfig()
deepAssign(_appConfig, appConfig)
}
// HMR Support
if (process.dev) {
function applyHMR (newConfig: AppConfig) {
const appConfig = useAppConfig()
if (newConfig && appConfig) {
deepAssign(appConfig, newConfig)
for (const key in appConfig) {
if (!(key in newConfig)) {
delete (appConfig as any)[key]
}
}
}
}
function deepAssign (obj: any, newObj: any) {
for (const key in newObj) {
const val = newObj[key]
if (val !== null && typeof val === 'object') {
deepAssign(obj[key], val)
} else {
obj[key] = val
}
deepDelete(appConfig, newConfig)
}
}

View File

@ -207,12 +207,13 @@ export const appConfigTemplate: NuxtTemplate = {
write: true,
getContents: ({ app, nuxt }) => {
return `
import defu from 'defu'
import { defuFn } from 'defu'
const inlineConfig = ${JSON.stringify(nuxt.options.appConfig, 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 defuFn(${app.configs.map((_id: string, index: number) => `cfg${index}`).concat(['inlineConfig']).join(', ')})
`
}
}

View File

@ -51,6 +51,7 @@ const appPreset = defineUnimportPreset({
'createError',
'defineNuxtLink',
'useAppConfig',
'updateAppConfig',
'defineAppConfig',
'preloadComponents',
'prefetchComponents'