mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-11 03:08:16 +00:00
feat(nuxt): support tracking changes to nuxt options by modules (#30555)
This commit is contained in:
parent
5e7d4938cd
commit
090bc6d7da
@ -28,7 +28,9 @@ export async function installModule<
|
||||
}
|
||||
|
||||
// Call module
|
||||
const res = await nuxtModule(inlineOptions || {}, nuxt) ?? {}
|
||||
const res = nuxt.options.experimental?.debugModuleMutation && nuxt._asyncLocalStorageModule
|
||||
? await nuxt._asyncLocalStorageModule.run(nuxtModule, () => nuxtModule(inlineOptions || {}, nuxt)) ?? {}
|
||||
: await nuxtModule(inlineOptions || {}, nuxt) ?? {}
|
||||
if (res === false /* setup aborted */) {
|
||||
return
|
||||
}
|
||||
@ -53,6 +55,7 @@ export async function installModule<
|
||||
|
||||
nuxt.options._installedModules.push({
|
||||
meta: defu(await nuxtModule.getMeta?.(), buildTimeModuleMeta),
|
||||
module: nuxtModule,
|
||||
timings: res.timings,
|
||||
entryPath,
|
||||
})
|
||||
|
@ -104,6 +104,7 @@
|
||||
"nypm": "^0.5.2",
|
||||
"ofetch": "^1.4.1",
|
||||
"ohash": "^1.1.4",
|
||||
"on-change": "^5.0.1",
|
||||
"pathe": "^2.0.2",
|
||||
"perfect-debounce": "^1.0.0",
|
||||
"pkg-types": "^1.3.1",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { existsSync } from 'node:fs'
|
||||
import { rm } from 'node:fs/promises'
|
||||
import { AsyncLocalStorage } from 'node:async_hooks'
|
||||
import { join, normalize, relative, resolve } from 'pathe'
|
||||
import { createDebugger, createHooks } from 'hookable'
|
||||
import ignore from 'ignore'
|
||||
@ -10,6 +11,7 @@ import type { PackageJson } from 'pkg-types'
|
||||
import { readPackageJSON } from 'pkg-types'
|
||||
import { hash } from 'ohash'
|
||||
import consola from 'consola'
|
||||
import onChange from 'on-change'
|
||||
import { colorize } from 'consola/utils'
|
||||
import { updateConfig } from 'c12/update'
|
||||
import { formatDate, resolveCompatibilityDatesFromEnv } from 'compatx'
|
||||
@ -53,7 +55,7 @@ export function createNuxt (options: NuxtOptions): Nuxt {
|
||||
|
||||
const nuxt: Nuxt = {
|
||||
_version: version,
|
||||
options,
|
||||
_asyncLocalStorageModule: options.experimental.debugModuleMutation ? new AsyncLocalStorage() : undefined,
|
||||
hooks,
|
||||
callHook: hooks.callHook,
|
||||
addHooks: hooks.addHooks,
|
||||
@ -62,6 +64,55 @@ export function createNuxt (options: NuxtOptions): Nuxt {
|
||||
close: () => hooks.callHook('close', nuxt),
|
||||
vfs: {},
|
||||
apps: {},
|
||||
options,
|
||||
}
|
||||
|
||||
if (options.experimental.debugModuleMutation) {
|
||||
const proxiedOptions = new WeakMap<NuxtModule, NuxtOptions>()
|
||||
|
||||
Object.defineProperty(nuxt, 'options', {
|
||||
get () {
|
||||
const currentModule = nuxt._asyncLocalStorageModule!.getStore()
|
||||
if (!currentModule) {
|
||||
return options
|
||||
}
|
||||
|
||||
if (proxiedOptions.has(currentModule)) {
|
||||
return proxiedOptions.get(currentModule)!
|
||||
}
|
||||
|
||||
nuxt._debug ||= {}
|
||||
nuxt._debug.moduleMutationRecords ||= []
|
||||
|
||||
const proxied = onChange(options, (keys, newValue, previousValue, applyData) => {
|
||||
if (newValue === previousValue && !applyData) {
|
||||
return
|
||||
}
|
||||
let value = applyData?.args ?? newValue
|
||||
// Make a shallow copy of the value
|
||||
if (Array.isArray(value)) {
|
||||
value = [...value]
|
||||
} else if (typeof value === 'object') {
|
||||
value = { ...(value as any) }
|
||||
}
|
||||
nuxt._debug!.moduleMutationRecords!.push({
|
||||
module: currentModule,
|
||||
keys,
|
||||
target: 'nuxt.options',
|
||||
value,
|
||||
timestamp: Date.now(),
|
||||
method: applyData?.name,
|
||||
})
|
||||
}, {
|
||||
ignoreUnderscores: true,
|
||||
ignoreSymbols: true,
|
||||
pathAsArray: true,
|
||||
})
|
||||
|
||||
proxiedOptions.set(currentModule, proxied)
|
||||
return proxied
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
hooks.hookOnce('close', () => { hooks.removeAllHooks() })
|
||||
|
@ -437,5 +437,14 @@ export default defineUntypedSchema({
|
||||
browserDevtoolsTiming: {
|
||||
$resolve: async (val, get) => val ?? await get('dev'),
|
||||
},
|
||||
|
||||
/**
|
||||
* Record mutations to `nuxt.options` in module context
|
||||
*/
|
||||
debugModuleMutation: {
|
||||
$resolve: async (val, get) => {
|
||||
return val ?? Boolean(await get('debug'))
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
@ -25,7 +25,7 @@ export default defineUntypedSchema({
|
||||
appDir: '',
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<{ meta: ModuleMeta; timings?: Record<string, number | undefined>; entryPath?: string }>}
|
||||
* @type {Array<{ meta: ModuleMeta; module: NuxtModule, timings?: Record<string, number | undefined>; entryPath?: string }>}
|
||||
*/
|
||||
_installedModules: [],
|
||||
/** @private */
|
||||
|
@ -8,7 +8,7 @@ export type { AppHeadMetaObject, MetaObject, MetaObjectRaw, HeadAugmentations }
|
||||
export type { ModuleDefinition, ModuleMeta, ModuleOptions, ModuleSetupInstallResult, ModuleSetupReturn, NuxtModule, ResolvedModuleOptions } from './types/module'
|
||||
export type { Nuxt, NuxtApp, NuxtPlugin, NuxtPluginTemplate, NuxtTemplate, NuxtTypeTemplate, NuxtServerTemplate, ResolvedNuxtTemplate } from './types/nuxt'
|
||||
export type { RouterConfig, RouterConfigSerializable, RouterOptions } from './types/router'
|
||||
export type { NuxtDebugOptions } from './types/debug'
|
||||
export type { NuxtDebugContext, NuxtDebugModuleMutationRecord } from './types/debug'
|
||||
|
||||
// Schema
|
||||
export { default as NuxtConfigSchema } from './config/index'
|
||||
|
@ -1,4 +1,21 @@
|
||||
import type { NitroOptions } from 'nitro/types'
|
||||
import type { NuxtModule } from './module'
|
||||
|
||||
export interface NuxtDebugContext {
|
||||
/**
|
||||
* Module mutation records to the `nuxt` instance.
|
||||
*/
|
||||
moduleMutationRecords?: NuxtDebugModuleMutationRecord[]
|
||||
}
|
||||
|
||||
export interface NuxtDebugModuleMutationRecord {
|
||||
module: NuxtModule
|
||||
keys: (string | symbol)[]
|
||||
target: 'nuxt.options'
|
||||
value: any
|
||||
method?: string
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
export interface NuxtDebugOptions {
|
||||
/** Debug for Nuxt templates */
|
||||
|
@ -1,8 +1,11 @@
|
||||
import type { AsyncLocalStorage } from 'node:async_hooks'
|
||||
import type { Hookable } from 'hookable'
|
||||
import type { Ignore } from 'ignore'
|
||||
import type { NuxtModule } from './module'
|
||||
import type { NuxtHooks, NuxtLayout, NuxtMiddleware, NuxtPage } from './hooks'
|
||||
import type { Component } from './components'
|
||||
import type { NuxtOptions } from './config'
|
||||
import type { NuxtDebugContext } from './debug'
|
||||
|
||||
export interface NuxtPlugin {
|
||||
/** @deprecated use mode */
|
||||
@ -83,6 +86,9 @@ export interface Nuxt {
|
||||
_version: string
|
||||
_ignore?: Ignore
|
||||
_dependencies?: Set<string>
|
||||
_debug?: NuxtDebugContext
|
||||
/** Async local storage for current running Nuxt module instance. */
|
||||
_asyncLocalStorageModule?: AsyncLocalStorage<NuxtModule>
|
||||
|
||||
/** The resolved Nuxt configuration. */
|
||||
options: NuxtOptions
|
||||
|
@ -444,6 +444,9 @@ importers:
|
||||
ohash:
|
||||
specifier: 1.1.4
|
||||
version: 1.1.4
|
||||
on-change:
|
||||
specifier: ^5.0.1
|
||||
version: 5.0.1
|
||||
pathe:
|
||||
specifier: ^2.0.2
|
||||
version: 2.0.2
|
||||
@ -6064,6 +6067,10 @@ packages:
|
||||
ohash@1.1.4:
|
||||
resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==}
|
||||
|
||||
on-change@5.0.1:
|
||||
resolution: {integrity: sha512-n7THCP7RkyReRSLkJb8kUWoNsxUIBxTkIp3JKno+sEz6o/9AJ3w3P9fzQkITEkMwyTKJjZciF3v/pVoouxZZMg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
on-finished@2.4.1:
|
||||
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -14067,6 +14074,8 @@ snapshots:
|
||||
|
||||
ohash@1.1.4: {}
|
||||
|
||||
on-change@5.0.1: {}
|
||||
|
||||
on-finished@2.4.1:
|
||||
dependencies:
|
||||
ee-first: 1.1.1
|
||||
|
Loading…
Reference in New Issue
Block a user