feat: provide name and allow multiple Nuxt App within the same process

This commit is contained in:
Julien Huang 2025-01-08 16:22:31 +01:00
parent 0acb893447
commit a848774138
6 changed files with 22 additions and 10 deletions

View File

@ -1,8 +1,9 @@
import { getContext } from 'unctx' import { getContext } from 'unctx'
import type { Nuxt } from '@nuxt/schema' import type { Nuxt } from '@nuxt/schema'
import { asyncNameStorage } from './utils'
/** Direct access to the Nuxt context - see https://github.com/unjs/unctx. */ /** Direct access to the Nuxt context - see https://github.com/unjs/unctx. */
export const nuxtCtx = getContext<Nuxt>('nuxt') export const nuxtCtx = () => getContext<Nuxt>(asyncNameStorage.getStore()!)
// TODO: Use use/tryUse from unctx. https://github.com/unjs/unctx/issues/6 // TODO: Use use/tryUse from unctx. https://github.com/unjs/unctx/issues/6
@ -16,7 +17,7 @@ export const nuxtCtx = getContext<Nuxt>('nuxt')
* ``` * ```
*/ */
export function useNuxt (): Nuxt { export function useNuxt (): Nuxt {
const instance = nuxtCtx.tryUse() const instance = nuxtCtx().tryUse()
if (!instance) { if (!instance) {
throw new Error('Nuxt instance is unavailable!') throw new Error('Nuxt instance is unavailable!')
} }
@ -36,5 +37,5 @@ export function useNuxt (): Nuxt {
* ``` * ```
*/ */
export function tryUseNuxt (): Nuxt | null { export function tryUseNuxt (): Nuxt | null {
return nuxtCtx.tryUse() return nuxtCtx().tryUse()
} }

View File

@ -35,3 +35,4 @@ export { logger, useLogger } from './logger'
export { resolveModule, tryResolveModule, importModule, tryImportModule, requireModule, tryRequireModule } from './internal/esm' export { resolveModule, tryResolveModule, importModule, tryImportModule, requireModule, tryRequireModule } from './internal/esm'
export type { ImportModuleOptions, ResolveModuleOptions } from './internal/esm' export type { ImportModuleOptions, ResolveModuleOptions } from './internal/esm'
export * from './internal/template' export * from './internal/template'
export { asyncNameStorage } from './utils'

View File

@ -1,6 +1,10 @@
import { AsyncLocalStorage } from "node:async_hooks"
/** @since 3.9.0 */ /** @since 3.9.0 */
export function toArray<T> (value: T | T[]): T[] { export function toArray<T> (value: T | T[]): T[] {
return Array.isArray(value) ? value : [value] return Array.isArray(value) ? value : [value]
} }
export const MODE_RE = /\.(server|client)(\.\w+)*$/ export const MODE_RE = /\.(server|client)(\.\w+)*$/
export const asyncNameStorage = new AsyncLocalStorage<string>()

View File

@ -429,7 +429,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
tsConfig.compilerOptions.paths[alias] = [absolutePath.replace(EXTENSION_RE, '')] /* remove extension */ tsConfig.compilerOptions.paths[alias] = [absolutePath.replace(EXTENSION_RE, '')] /* remove extension */
} }
} }
// Init nitro // Init nitro
const nitro = await createNitro(nitroConfig, { const nitro = await createNitro(nitroConfig, {
compatibilityDate: nuxt.options.compatibilityDate, compatibilityDate: nuxt.options.compatibilityDate,

View File

@ -4,7 +4,7 @@ import { join, normalize, relative, resolve } from 'pathe'
import { createDebugger, createHooks } from 'hookable' import { createDebugger, createHooks } from 'hookable'
import ignore from 'ignore' import ignore from 'ignore'
import type { LoadNuxtOptions } from '@nuxt/kit' import type { LoadNuxtOptions } from '@nuxt/kit'
import { addBuildPlugin, addComponent, addPlugin, addPluginTemplate, addRouteMiddleware, addServerPlugin, addTypeTemplate, addVitePlugin, addWebpackPlugin, installModule, loadNuxtConfig, nuxtCtx, resolveAlias, resolveFiles, resolveIgnorePatterns, resolvePath, tryResolveModule, useNitro } from '@nuxt/kit' import { addBuildPlugin, addComponent, addPlugin, addPluginTemplate, addRouteMiddleware, addServerPlugin, addTypeTemplate, addVitePlugin, addWebpackPlugin, installModule, loadNuxtConfig, nuxtCtx, resolveAlias, resolveFiles, resolveIgnorePatterns, resolvePath, tryResolveModule, useNitro, asyncNameStorage } from '@nuxt/kit'
import type { Nuxt, NuxtHooks, NuxtModule, NuxtOptions } from 'nuxt/schema' import type { Nuxt, NuxtHooks, NuxtModule, NuxtOptions } from 'nuxt/schema'
import type { PackageJson } from 'pkg-types' import type { PackageJson } from 'pkg-types'
import { readPackageJSON } from 'pkg-types' import { readPackageJSON } from 'pkg-types'
@ -46,10 +46,11 @@ import { ComposableKeysPlugin } from './plugins/composable-keys'
import { resolveDeepImportsPlugin } from './plugins/resolve-deep-imports' import { resolveDeepImportsPlugin } from './plugins/resolve-deep-imports'
import { PrehydrateTransformPlugin } from './plugins/prehydrate' import { PrehydrateTransformPlugin } from './plugins/prehydrate'
import { VirtualFSPlugin } from './plugins/virtual' import { VirtualFSPlugin } from './plugins/virtual'
import { randomUUID } from 'node:crypto'
export function createNuxt (options: NuxtOptions): Nuxt { export function createNuxt (options: NuxtOptions): Nuxt {
const hooks = createHooks<NuxtHooks>() const hooks = createHooks<NuxtHooks>()
const name = randomUUID()
const nuxt: Nuxt = { const nuxt: Nuxt = {
_version: version, _version: version,
options, options,
@ -57,7 +58,7 @@ export function createNuxt (options: NuxtOptions): Nuxt {
callHook: hooks.callHook, callHook: hooks.callHook,
addHooks: hooks.addHooks, addHooks: hooks.addHooks,
hook: hooks.hook, hook: hooks.hook,
ready: () => initNuxt(nuxt), ready: () => asyncNameStorage.run(name, () => initNuxt(nuxt)) ,
close: () => hooks.callHook('close', nuxt), close: () => hooks.callHook('close', nuxt),
vfs: {}, vfs: {},
apps: {}, apps: {},
@ -173,8 +174,8 @@ async function initNuxt (nuxt: Nuxt) {
}) })
// Set nuxt instance for useNuxt // Set nuxt instance for useNuxt
nuxtCtx.set(nuxt) nuxtCtx().set(nuxt)
nuxt.hook('close', () => nuxtCtx.unset()) nuxt.hook('close', () => nuxtCtx().unset())
const coreTypePackages = nuxt.options.typescript.hoist || [] const coreTypePackages = nuxt.options.typescript.hoist || []
@ -693,7 +694,7 @@ export default defineNuxtPlugin({
nuxt.options.build.transpile = nuxt.options.build.transpile.map(t => typeof t === 'string' ? normalize(t) : t) nuxt.options.build.transpile = nuxt.options.build.transpile.map(t => typeof t === 'string' ? normalize(t) : t)
addModuleTranspiles() addModuleTranspiles()
// Init nitro // Init nitro
await initNitro(nuxt) await initNitro(nuxt)

View File

@ -79,6 +79,11 @@ export interface NuxtApp {
} }
export interface Nuxt { export interface Nuxt {
/**
* The name of the Nuxt project, this can be useful for build time debugging and mono-repos.
* Defaults to a randomUUID
*/
name?: string
// Private fields. // Private fields.
_version: string _version: string
_ignore?: Ignore _ignore?: Ignore