feat(nuxt): allow specifying app id when creating a nuxt app (#28392)

This commit is contained in:
Tobias Diez 2024-08-06 17:41:51 +02:00 committed by Daniel Roe
parent 13ba46bec3
commit 45d92d67ee
No known key found for this signature in database
GPG Key ID: 3714AB03996F442B
3 changed files with 30 additions and 17 deletions

View File

@ -7,6 +7,8 @@ const SEPARATOR = '-'
/** /**
* Generate an SSR-friendly unique identifier that can be passed to accessibility attributes. * Generate an SSR-friendly unique identifier that can be passed to accessibility attributes.
*
* The generated ID is unique in the context of the current Nuxt instance and key.
*/ */
export function useId (): string export function useId (): string
export function useId (key?: string): string { export function useId (key?: string): string {
@ -24,7 +26,7 @@ export function useId (key?: string): string {
throw new TypeError('[nuxt] `useId` must be called within a component setup function.') throw new TypeError('[nuxt] `useId` must be called within a component setup function.')
} }
nuxtApp._id ||= 0 nuxtApp._genId ||= 0
instance._nuxtIdIndex ||= {} instance._nuxtIdIndex ||= {}
instance._nuxtIdIndex[key] ||= 0 instance._nuxtIdIndex[key] ||= 0
@ -32,7 +34,7 @@ export function useId (key?: string): string {
if (import.meta.server) { if (import.meta.server) {
const ids = JSON.parse(instance.attrs[ATTR_KEY] as string | undefined || '{}') const ids = JSON.parse(instance.attrs[ATTR_KEY] as string | undefined || '{}')
ids[instanceIndex] = key + SEPARATOR + nuxtApp._id++ ids[instanceIndex] = key + SEPARATOR + nuxtApp._genId++
instance.attrs[ATTR_KEY] = JSON.stringify(ids) instance.attrs[ATTR_KEY] = JSON.stringify(ids)
return ids[instanceIndex] return ids[instanceIndex]
} }
@ -54,5 +56,5 @@ export function useId (key?: string): string {
} }
// pure client-side ids, avoiding potential collision with server-side ids // pure client-side ids, avoiding potential collision with server-side ids
return key + '_' + nuxtApp._id++ return key + '_' + nuxtApp._genId++
} }

View File

@ -27,8 +27,8 @@ import { appId } from '#build/nuxt.config.mjs'
import type { DefaultAsyncDataErrorValue, DefaultErrorValue } from '#app/defaults' import type { DefaultAsyncDataErrorValue, DefaultErrorValue } from '#app/defaults'
import type { NuxtAppLiterals } from '#app' import type { NuxtAppLiterals } from '#app'
function getNuxtAppCtx (appName = appId || 'nuxt-app') { function getNuxtAppCtx (id = appId || 'nuxt-app') {
return getContext<NuxtApp>(appName, { return getContext<NuxtApp>(id, {
asyncContext: !!__NUXT_ASYNC_CONTEXT__ && import.meta.server, asyncContext: !!__NUXT_ASYNC_CONTEXT__ && import.meta.server,
}) })
} }
@ -100,8 +100,6 @@ export interface NuxtPayload {
} }
interface _NuxtApp { interface _NuxtApp {
/** @internal */
_name: string
vueApp: App<Element> vueApp: App<Element>
globalName: string globalName: string
versions: Record<string, string> versions: Record<string, string>
@ -116,8 +114,15 @@ interface _NuxtApp {
/** @internal */ /** @internal */
_cookies?: Record<string, unknown> _cookies?: Record<string, unknown>
/** @internal */ /**
_id?: number * The id of the Nuxt application.
* @internal */
_id: string
/**
* The next id that can be used for generating unique ids via `useId`.
* @internal
*/
_genId?: number
/** @internal */ /** @internal */
_scope: EffectScope _scope: EffectScope
/** @internal */ /** @internal */
@ -248,13 +253,17 @@ export interface CreateOptions {
vueApp: NuxtApp['vueApp'] vueApp: NuxtApp['vueApp']
ssrContext?: NuxtApp['ssrContext'] ssrContext?: NuxtApp['ssrContext']
globalName?: NuxtApp['globalName'] globalName?: NuxtApp['globalName']
/**
* The id of the Nuxt application, overrides the default id specified in the Nuxt config (default: `nuxt-app`).
*/
id?: NuxtApp['_id']
} }
/** @since 3.0.0 */ /** @since 3.0.0 */
export function createNuxtApp (options: CreateOptions) { export function createNuxtApp (options: CreateOptions) {
let hydratingCount = 0 let hydratingCount = 0
const nuxtApp: NuxtApp = { const nuxtApp: NuxtApp = {
_name: appId || 'nuxt-app', _id: options.id || appId || 'nuxt-app',
_scope: effectScope(), _scope: effectScope(),
provide: undefined, provide: undefined,
globalName: 'nuxt', globalName: 'nuxt',
@ -494,7 +503,7 @@ export function isNuxtPlugin (plugin: unknown) {
*/ */
export function callWithNuxt<T extends (...args: any[]) => any> (nuxt: NuxtApp | _NuxtApp, setup: T, args?: Parameters<T>) { export function callWithNuxt<T extends (...args: any[]) => any> (nuxt: NuxtApp | _NuxtApp, setup: T, args?: Parameters<T>) {
const fn: () => ReturnType<T> = () => args ? setup(...args as Parameters<T>) : setup() const fn: () => ReturnType<T> = () => args ? setup(...args as Parameters<T>) : setup()
const nuxtAppCtx = getNuxtAppCtx(nuxt._name) const nuxtAppCtx = getNuxtAppCtx(nuxt._id)
if (import.meta.server) { if (import.meta.server) {
return nuxt.vueApp.runWithContext(() => nuxtAppCtx.callAsync(nuxt as NuxtApp, fn)) return nuxt.vueApp.runWithContext(() => nuxtAppCtx.callAsync(nuxt as NuxtApp, fn))
} else { } else {
@ -512,13 +521,13 @@ export function callWithNuxt<T extends (...args: any[]) => any> (nuxt: NuxtApp |
* @since 3.10.0 * @since 3.10.0
*/ */
export function tryUseNuxtApp (): NuxtApp | null export function tryUseNuxtApp (): NuxtApp | null
export function tryUseNuxtApp (appName?: string): NuxtApp | null { export function tryUseNuxtApp (id?: string): NuxtApp | null {
let nuxtAppInstance let nuxtAppInstance
if (hasInjectionContext()) { if (hasInjectionContext()) {
nuxtAppInstance = getCurrentInstance()?.appContext.app.$nuxt nuxtAppInstance = getCurrentInstance()?.appContext.app.$nuxt
} }
nuxtAppInstance = nuxtAppInstance || getNuxtAppCtx(appName).tryUse() nuxtAppInstance = nuxtAppInstance || getNuxtAppCtx(id).tryUse()
return nuxtAppInstance || null return nuxtAppInstance || null
} }
@ -531,9 +540,9 @@ export function tryUseNuxtApp (appName?: string): NuxtApp | null {
* @since 3.0.0 * @since 3.0.0
*/ */
export function useNuxtApp (): NuxtApp export function useNuxtApp (): NuxtApp
export function useNuxtApp (appName?: string): NuxtApp { export function useNuxtApp (id?: string): NuxtApp {
// @ts-expect-error internal usage of appName // @ts-expect-error internal usage of id
const nuxtAppInstance = tryUseNuxtApp(appName) const nuxtAppInstance = tryUseNuxtApp(id)
if (!nuxtAppInstance) { if (!nuxtAppInstance) {
if (import.meta.dev) { if (import.meta.dev) {

View File

@ -179,7 +179,9 @@ export default defineUntypedSchema({
}, },
/** /**
* For multi-app projects, the unique name of the Nuxt application. * For multi-app projects, the unique id of the Nuxt application.
*
* Defaults to `nuxt-app`.
*/ */
appId: { appId: {
$resolve: (val: string) => val ?? 'nuxt-app', $resolve: (val: string) => val ?? 'nuxt-app',