mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-22 11:22:43 +00:00
feat: provide fallback instance for backward compatibility
This commit is contained in:
parent
186be43db1
commit
705e221bbd
@ -1,9 +1,11 @@
|
|||||||
import { getContext } from 'unctx'
|
import { getContext } from 'unctx'
|
||||||
import type { Nuxt } from '@nuxt/schema'
|
import type { Nuxt } from '@nuxt/schema'
|
||||||
import { asyncNameStorage } from './utils'
|
import { asyncNameStorage } from './utils'
|
||||||
|
import { logger } from './logger'
|
||||||
|
|
||||||
/** 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>(asyncNameStorage.getStore()!)
|
export const nuxtCtx = () => getContext<Nuxt>(asyncNameStorage.getStore()!)
|
||||||
|
export const fallbackNuxtCtx = getContext<Nuxt>('nuxt-fallback')
|
||||||
|
|
||||||
// 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
|
||||||
|
|
||||||
@ -19,6 +21,11 @@ export const nuxtCtx = () => getContext<Nuxt>(asyncNameStorage.getStore()!)
|
|||||||
export function useNuxt (): Nuxt {
|
export function useNuxt (): Nuxt {
|
||||||
const instance = nuxtCtx().tryUse()
|
const instance = nuxtCtx().tryUse()
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
|
const fallbackInstance = fallbackNuxtCtx.tryUse()
|
||||||
|
if (fallbackInstance) {
|
||||||
|
logger.warn('Using fallback global Nuxt instance. You may be using a @nuxt/kit composable outside of a Nuxt context, this behavior is deprecated and will be removed in v4.')
|
||||||
|
return fallbackInstance }
|
||||||
|
|
||||||
throw new Error('Nuxt instance is unavailable!')
|
throw new Error('Nuxt instance is unavailable!')
|
||||||
}
|
}
|
||||||
return instance
|
return instance
|
||||||
@ -37,5 +44,10 @@ export function useNuxt (): Nuxt {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function tryUseNuxt (): Nuxt | null {
|
export function tryUseNuxt (): Nuxt | null {
|
||||||
return nuxtCtx().tryUse()
|
const nuxt = nuxtCtx().tryUse()
|
||||||
|
if(!nuxt) {
|
||||||
|
logger.warn('Using fallback global Nuxt instance. You may be using a @nuxt/kit composable outside of a Nuxt context, this behavior is deprecated and will be removed in v4.')
|
||||||
|
return fallbackNuxtCtx.tryUse()
|
||||||
|
}
|
||||||
|
return nuxt
|
||||||
}
|
}
|
||||||
|
@ -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, asyncNameStorage } from '@nuxt/kit'
|
import { addBuildPlugin, addComponent, addPlugin, addPluginTemplate, addRouteMiddleware, addServerPlugin, addTypeTemplate, addVitePlugin, addWebpackPlugin, installModule, loadNuxtConfig, nuxtCtx, resolveAlias, resolveFiles, resolveIgnorePatterns, resolvePath, tryResolveModule, useNitro, asyncNameStorage, fallbackNuxtCtx } 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'
|
||||||
@ -49,7 +49,7 @@ import { PrehydrateTransformPlugin } from './plugins/prehydrate'
|
|||||||
import { VirtualFSPlugin } from './plugins/virtual'
|
import { VirtualFSPlugin } from './plugins/virtual'
|
||||||
import { randomUUID } from 'uncrypto'
|
import { randomUUID } from 'uncrypto'
|
||||||
|
|
||||||
export function createNuxt (options: NuxtOptions): Nuxt {
|
export function createNuxt(options: NuxtOptions): Nuxt {
|
||||||
const hooks = createHooks<NuxtHooks>()
|
const hooks = createHooks<NuxtHooks>()
|
||||||
const name = randomUUID()
|
const name = randomUUID()
|
||||||
const nuxt: Nuxt = {
|
const nuxt: Nuxt = {
|
||||||
@ -59,7 +59,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: () => asyncNameStorage.run(name, () => initNuxt(nuxt)) ,
|
ready: () => asyncNameStorage.run(name, () => initNuxt(nuxt)),
|
||||||
close: () => hooks.callHook('close', nuxt),
|
close: () => hooks.callHook('close', nuxt),
|
||||||
vfs: {},
|
vfs: {},
|
||||||
apps: {},
|
apps: {},
|
||||||
@ -90,7 +90,7 @@ const keyDependencies = [
|
|||||||
|
|
||||||
let warnedAboutCompatDate = false
|
let warnedAboutCompatDate = false
|
||||||
|
|
||||||
async function initNuxt (nuxt: Nuxt) {
|
async function initNuxt(nuxt: Nuxt) {
|
||||||
// Register user hooks
|
// Register user hooks
|
||||||
for (const config of nuxt.options._layers.map(layer => layer.config).reverse()) {
|
for (const config of nuxt.options._layers.map(layer => layer.config).reverse()) {
|
||||||
if (config.hooks) {
|
if (config.hooks) {
|
||||||
@ -110,7 +110,7 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
logger.info(`Using \`${fallbackCompatibilityDate}\` as fallback compatibility date.`)
|
logger.info(`Using \`${fallbackCompatibilityDate}\` as fallback compatibility date.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function promptAndUpdate () {
|
async function promptAndUpdate() {
|
||||||
const result = await consola.prompt(`Do you want to update your ${colorize('cyan', 'nuxt.config')} to set ${colorize('cyan', `compatibilityDate: '${todaysDate}'`)}?`, {
|
const result = await consola.prompt(`Do you want to update your ${colorize('cyan', 'nuxt.config')} to set ${colorize('cyan', `compatibilityDate: '${todaysDate}'`)}?`, {
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
default: true,
|
default: true,
|
||||||
@ -124,7 +124,7 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
const res = await updateConfig({
|
const res = await updateConfig({
|
||||||
configFile: 'nuxt.config',
|
configFile: 'nuxt.config',
|
||||||
cwd: nuxt.options.rootDir,
|
cwd: nuxt.options.rootDir,
|
||||||
async onCreate ({ configFile }) {
|
async onCreate({ configFile }) {
|
||||||
const shallCreate = await consola.prompt(`Do you want to create ${colorize('cyan', relative(nuxt.options.rootDir, configFile))}?`, {
|
const shallCreate = await consola.prompt(`Do you want to create ${colorize('cyan', relative(nuxt.options.rootDir, configFile))}?`, {
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
default: true,
|
default: true,
|
||||||
@ -134,7 +134,7 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
}
|
}
|
||||||
return _getDefaultNuxtConfig()
|
return _getDefaultNuxtConfig()
|
||||||
},
|
},
|
||||||
onUpdate (config) {
|
onUpdate(config) {
|
||||||
config.compatibilityDate = todaysDate
|
config.compatibilityDate = todaysDate
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -175,10 +175,18 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if (!fallbackNuxtCtx.tryUse()) {
|
||||||
|
// backward compatibility with 3.x
|
||||||
|
fallbackNuxtCtx.set(nuxt)
|
||||||
|
nuxt.hook('close', () => {
|
||||||
|
fallbackNuxtCtx.unset()
|
||||||
|
})
|
||||||
|
}
|
||||||
// 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 || []
|
||||||
|
|
||||||
@ -723,7 +731,7 @@ export default defineNuxtPlugin({
|
|||||||
await nuxt.callHook('ready', nuxt)
|
await nuxt.callHook('ready', nuxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
export async function loadNuxt(opts: LoadNuxtOptions): Promise<Nuxt> {
|
||||||
const options = await loadNuxtConfig(opts)
|
const options = await loadNuxtConfig(opts)
|
||||||
|
|
||||||
// Temporary until finding better placement for each
|
// Temporary until finding better placement for each
|
||||||
@ -796,7 +804,7 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
|||||||
configurable: false,
|
configurable: false,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
get: () => nitroOptions,
|
get: () => nitroOptions,
|
||||||
set (value) {
|
set(value) {
|
||||||
Object.assign(nitroOptions, value)
|
Object.assign(nitroOptions, value)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -824,7 +832,7 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
|||||||
return nuxt
|
return nuxt
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkDependencyVersion (name: string, nuxtVersion: string): Promise<void> {
|
async function checkDependencyVersion(name: string, nuxtVersion: string): Promise<void> {
|
||||||
const path = await resolvePath(name, { fallbackToOriginal: true }).catch(() => null)
|
const path = await resolvePath(name, { fallbackToOriginal: true }).catch(() => null)
|
||||||
|
|
||||||
if (!path || path === name) { return }
|
if (!path || path === name) { return }
|
||||||
@ -837,7 +845,7 @@ async function checkDependencyVersion (name: string, nuxtVersion: string): Promi
|
|||||||
|
|
||||||
const RESTART_RE = /^(?:app|error|app\.config)\.(?:js|ts|mjs|jsx|tsx|vue)$/i
|
const RESTART_RE = /^(?:app|error|app\.config)\.(?:js|ts|mjs|jsx|tsx|vue)$/i
|
||||||
|
|
||||||
function deduplicateArray<T = unknown> (maybeArray: T): T {
|
function deduplicateArray<T = unknown>(maybeArray: T): T {
|
||||||
if (!Array.isArray(maybeArray)) { return maybeArray }
|
if (!Array.isArray(maybeArray)) { return maybeArray }
|
||||||
|
|
||||||
const fresh: any[] = []
|
const fresh: any[] = []
|
||||||
@ -852,7 +860,7 @@ function deduplicateArray<T = unknown> (maybeArray: T): T {
|
|||||||
return fresh as T
|
return fresh as T
|
||||||
}
|
}
|
||||||
|
|
||||||
function createPortalProperties (sourceValue: any, options: NuxtOptions, paths: string[]) {
|
function createPortalProperties(sourceValue: any, options: NuxtOptions, paths: string[]) {
|
||||||
let sharedValue = sourceValue
|
let sharedValue = sourceValue
|
||||||
|
|
||||||
for (const path of paths) {
|
for (const path of paths) {
|
||||||
@ -872,7 +880,7 @@ function createPortalProperties (sourceValue: any, options: NuxtOptions, paths:
|
|||||||
configurable: false,
|
configurable: false,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
get: () => sharedValue,
|
get: () => sharedValue,
|
||||||
set (value) {
|
set(value) {
|
||||||
sharedValue = value
|
sharedValue = value
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -35,7 +35,7 @@ describe('loadNuxt', () => {
|
|||||||
ready: true,
|
ready: true,
|
||||||
overrides: {
|
overrides: {
|
||||||
hooks: {
|
hooks: {
|
||||||
ready () {
|
ready() {
|
||||||
hookRan = true
|
hookRan = true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -44,6 +44,16 @@ describe('loadNuxt', () => {
|
|||||||
await nuxt.close()
|
await nuxt.close()
|
||||||
expect(hookRan).toBe(true)
|
expect(hookRan).toBe(true)
|
||||||
})
|
})
|
||||||
|
it('load multiple nuxt', async () => {
|
||||||
|
await Promise.all([
|
||||||
|
loadNuxt({
|
||||||
|
cwd: repoRoot,
|
||||||
|
}),
|
||||||
|
loadNuxt({
|
||||||
|
cwd: repoRoot,
|
||||||
|
})
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('dependency mismatch', () => {
|
describe('dependency mismatch', () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user