mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
feat(nuxt): support object-syntax plugins (#20003)
This commit is contained in:
parent
f951a15232
commit
4285092879
@ -40,6 +40,31 @@ export default defineNuxtPlugin(nuxtApp => {
|
||||
})
|
||||
```
|
||||
|
||||
### Object Syntax Plugins
|
||||
|
||||
It is also possible to define a plugin using an object syntax, for more advanced use cases. For example:
|
||||
|
||||
```ts
|
||||
export default defineNuxtPlugin({
|
||||
name: 'my-plugin',
|
||||
enforce: 'pre', // or 'post'
|
||||
async setup (nuxtApp) {
|
||||
// this is the equivalent of a normal functional plugin
|
||||
},
|
||||
hooks: {
|
||||
// You can directly register Nuxt app hooks here
|
||||
'app:created'() {
|
||||
const nuxtApp = useNuxtApp()
|
||||
//
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::alert
|
||||
If you are using an object-syntax plugin, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. For example, setting `enforce: process.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
|
||||
::
|
||||
|
||||
## Plugin Registration Order
|
||||
|
||||
You can control the order in which plugins are registered by prefixing a number to the file names.
|
||||
|
@ -116,19 +116,19 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
::alert
|
||||
Normally `payload` must contain only plain JavaScript objects. But by setting `experimental.renderJsonPayloads`, it is possible to use more advanced types, such as `ref`, `reactive`, `shallowRef`, `shallowReactive` and `NuxtError`.
|
||||
|
||||
You can also add your own types. In future you will be able to add your own types easily with [object-syntax plugins](https://github.com/nuxt/nuxt/issues/14628). For now, you must add your plugin which calls both `definePayloadReducer` and `definePayloadReviver` via a custom module:
|
||||
You can also add your own types, with a special plugin helper:
|
||||
|
||||
```ts
|
||||
export default defineNuxtConfig({
|
||||
modules: [
|
||||
function (_options, nuxt) {
|
||||
// TODO: support directly via object syntax plugins: https://github.com/nuxt/nuxt/issues/14628
|
||||
nuxt.hook('modules:done', () => {
|
||||
nuxt.options.plugins.unshift('~/plugins/custom-type-plugin')
|
||||
})
|
||||
},
|
||||
]
|
||||
```ts [plugins/custom-payload.ts]
|
||||
/**
|
||||
* This kind of plugin runs very early in the Nuxt lifecycle, before we revive the payload.
|
||||
* You will not have access to the router or other Nuxt-injected properties.
|
||||
*/
|
||||
export default definePayloadPlugin((nuxtApp) => {
|
||||
definePayloadReducer('BlinkingText', data => data === '<blink>' && '_')
|
||||
definePayloadReviver('BlinkingText', () => '<blink>')
|
||||
})
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
### `isHydrating`
|
||||
|
@ -139,9 +139,31 @@ interface _NuxtApp {
|
||||
export interface NuxtApp extends _NuxtApp {}
|
||||
|
||||
export const NuxtPluginIndicator = '__nuxt_plugin'
|
||||
|
||||
export interface PluginMeta {
|
||||
name?: string
|
||||
enforce?: 'pre' | 'default' | 'post'
|
||||
/**
|
||||
* This allows more granular control over plugin order and should only be used by advanced users.
|
||||
* It overrides the value of `enforce` and is used to sort plugins.
|
||||
*/
|
||||
order?: number
|
||||
}
|
||||
|
||||
export interface ResolvedPluginMeta {
|
||||
name?: string
|
||||
order: number
|
||||
}
|
||||
|
||||
export interface Plugin<Injections extends Record<string, unknown> = Record<string, unknown>> {
|
||||
(nuxt: _NuxtApp): Promise<void> | Promise<{ provide?: Injections }> | void | { provide?: Injections }
|
||||
[NuxtPluginIndicator]?: true
|
||||
meta?: ResolvedPluginMeta
|
||||
}
|
||||
|
||||
export interface ObjectPluginInput<Injections extends Record<string, unknown> = Record<string, unknown>> extends PluginMeta {
|
||||
hooks?: Partial<RuntimeNuxtHooks>
|
||||
setup?: Plugin<Injections>
|
||||
}
|
||||
|
||||
export interface CreateOptions {
|
||||
@ -306,25 +328,30 @@ export function normalizePlugins (_plugins: Plugin[]) {
|
||||
const legacyInjectPlugins: Plugin[] = []
|
||||
const invalidPlugins: Plugin[] = []
|
||||
|
||||
const plugins = _plugins.map((plugin) => {
|
||||
const plugins: Plugin[] = []
|
||||
|
||||
for (const plugin of _plugins) {
|
||||
if (typeof plugin !== 'function') {
|
||||
invalidPlugins.push(plugin)
|
||||
return null
|
||||
if (process.dev) { invalidPlugins.push(plugin) }
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: Skip invalid plugins in next releases
|
||||
let _plugin = plugin
|
||||
if (plugin.length > 1) {
|
||||
legacyInjectPlugins.push(plugin)
|
||||
// Allow usage without wrapper but warn
|
||||
// TODO: Skip invalid in next releases
|
||||
// @ts-ignore
|
||||
return (nuxtApp: NuxtApp) => plugin(nuxtApp, nuxtApp.provide)
|
||||
// return null
|
||||
if (process.dev) { legacyInjectPlugins.push(plugin) }
|
||||
// @ts-expect-error deliberate invalid second argument
|
||||
_plugin = (nuxtApp: NuxtApp) => plugin(nuxtApp, nuxtApp.provide)
|
||||
}
|
||||
if (!isNuxtPlugin(plugin)) {
|
||||
unwrappedPlugins.push(plugin)
|
||||
|
||||
// Allow usage without wrapper but warn
|
||||
if (process.dev && !isNuxtPlugin(_plugin)) { unwrappedPlugins.push(_plugin) }
|
||||
|
||||
plugins.push(_plugin)
|
||||
}
|
||||
return plugin
|
||||
}).filter(Boolean)
|
||||
|
||||
plugins.sort((a, b) => (a.meta?.order || orderMap.default) - (b.meta?.order || orderMap.default))
|
||||
|
||||
if (process.dev && legacyInjectPlugins.length) {
|
||||
console.warn('[warn] [nuxt] You are using a plugin with legacy Nuxt 2 format (context, inject) which is likely to be broken. In the future they will be ignored:', legacyInjectPlugins.map(p => p.name || p).join(','))
|
||||
@ -336,12 +363,53 @@ export function normalizePlugins (_plugins: Plugin[]) {
|
||||
console.warn('[warn] [nuxt] You are using a plugin that has not been wrapped in `defineNuxtPlugin`. It is advised to wrap your plugins as in the future this may enable enhancements:', unwrappedPlugins.map(p => p.name || p).join(','))
|
||||
}
|
||||
|
||||
return plugins as Plugin[]
|
||||
return plugins
|
||||
}
|
||||
|
||||
export function defineNuxtPlugin<T extends Record<string, unknown>> (plugin: Plugin<T>) {
|
||||
plugin[NuxtPluginIndicator] = true
|
||||
return plugin
|
||||
// -50: pre-all (nuxt)
|
||||
// -40: custom payload revivers (user)
|
||||
// -30: payload reviving (nuxt)
|
||||
// -20: pre (user) <-- pre mapped to this
|
||||
// -10: default (nuxt)
|
||||
// 0: default (user) <-- default behavior
|
||||
// +10: post (nuxt)
|
||||
// +20: post (user) <-- post mapped to this
|
||||
// +30: post-all (nuxt)
|
||||
|
||||
const orderMap: Record<NonNullable<ObjectPluginInput['enforce']>, number> = {
|
||||
pre: -20,
|
||||
default: 0,
|
||||
post: 20
|
||||
}
|
||||
|
||||
export function definePayloadPlugin<T extends Record<string, unknown>> (plugin: Plugin<T> | ObjectPluginInput<T>) {
|
||||
return defineNuxtPlugin(plugin, { order: -40 })
|
||||
}
|
||||
|
||||
export function defineNuxtPlugin<T extends Record<string, unknown>> (plugin: Plugin<T> | ObjectPluginInput<T>, meta?: PluginMeta): Plugin<T> {
|
||||
if (typeof plugin === 'function') { return defineNuxtPlugin({ setup: plugin }, meta) }
|
||||
|
||||
const wrapper: Plugin<T> = (nuxtApp) => {
|
||||
if (plugin.hooks) {
|
||||
nuxtApp.hooks.addHooks(plugin.hooks)
|
||||
}
|
||||
if (plugin.setup) {
|
||||
return plugin.setup(nuxtApp)
|
||||
}
|
||||
}
|
||||
|
||||
wrapper.meta = {
|
||||
name: meta?.name || plugin.name || plugin.setup?.name,
|
||||
order:
|
||||
meta?.order ||
|
||||
plugin.order ||
|
||||
orderMap[plugin.enforce || 'default'] ||
|
||||
orderMap.default
|
||||
}
|
||||
|
||||
wrapper[NuxtPluginIndicator] = true
|
||||
|
||||
return wrapper
|
||||
}
|
||||
|
||||
export function isNuxtPlugin (plugin: unknown) {
|
||||
|
@ -3,7 +3,9 @@ import { defineNuxtPlugin, useRuntimeConfig } from '#app/nuxt'
|
||||
import { useRouter } from '#app/composables/router'
|
||||
import { reloadNuxtApp } from '#app/composables/chunk'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:chunk-reload',
|
||||
setup (nuxtApp) {
|
||||
const router = useRouter()
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
@ -19,4 +21,5 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
reloadNuxtApp({ path, persistState: true })
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -3,7 +3,9 @@ import { parseURL } from 'ufo'
|
||||
import { useHead } from '@unhead/vue'
|
||||
import { defineNuxtPlugin } from '#app/nuxt'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:cross-origin-prefetch',
|
||||
setup (nuxtApp) {
|
||||
const externalURLs = ref(new Set<string>())
|
||||
function generateRules () {
|
||||
return {
|
||||
@ -32,4 +34,5 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { createDebugger } from 'hookable'
|
||||
import { defineNuxtPlugin } from '#app/nuxt'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:debug',
|
||||
enforce: 'pre',
|
||||
setup (nuxtApp) {
|
||||
createDebugger(nuxtApp.hooks, { tag: 'nuxt-app' })
|
||||
}
|
||||
})
|
||||
|
@ -3,7 +3,9 @@ import { defineNuxtPlugin } from '#app/nuxt'
|
||||
import { isPrerendered, loadPayload } from '#app/composables/payload'
|
||||
import { useRouter } from '#app/composables/router'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:payload',
|
||||
setup (nuxtApp) {
|
||||
// Only enable behavior if initial page is prerendered
|
||||
// TODO: Support hybrid and dev
|
||||
if (!isPrerendered()) {
|
||||
@ -24,4 +26,5 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
if (!payload) { return }
|
||||
Object.assign(nuxtApp.static.data, payload.data)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { defineNuxtPlugin } from '#app/nuxt'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:webpack-preload',
|
||||
setup (nuxtApp) {
|
||||
nuxtApp.vueApp.mixin({
|
||||
beforeCreate () {
|
||||
const { _registeredComponents } = this.$nuxt.ssrContext
|
||||
@ -8,4 +10,5 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
_registeredComponents.add(__moduleIdentifier)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { defineNuxtPlugin } from '#app/nuxt'
|
||||
import { defineNuxtPlugin, useNuxtApp } from '#app/nuxt'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
nuxtApp.hook('app:mounted', () => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:restore-state',
|
||||
hooks: {
|
||||
'app:mounted' () {
|
||||
const nuxtApp = useNuxtApp()
|
||||
try {
|
||||
const state = sessionStorage.getItem('nuxt:reload:state')
|
||||
if (state) {
|
||||
@ -9,5 +12,6 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
Object.assign(nuxtApp.payload.state, JSON.parse(state)?.state)
|
||||
}
|
||||
} catch {}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -13,11 +13,15 @@ const revivers = {
|
||||
Reactive: (data: any) => reactive(data)
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin(async (nuxtApp) => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:revive-payload:client',
|
||||
order: -30,
|
||||
async setup (nuxtApp) {
|
||||
for (const reviver in revivers) {
|
||||
definePayloadReviver(reviver, revivers[reviver as keyof typeof revivers])
|
||||
}
|
||||
Object.assign(nuxtApp.payload, await callWithNuxt(nuxtApp, getNuxtClientPayload, []))
|
||||
// For backwards compatibility - TODO: remove later
|
||||
window.__NUXT__ = nuxtApp.payload
|
||||
}
|
||||
})
|
||||
|
@ -14,8 +14,11 @@ const reducers = {
|
||||
Reactive: (data: any) => isReactive(data) && toRaw(data)
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin(() => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:revive-payload:server',
|
||||
setup () {
|
||||
for (const reducer in reducers) {
|
||||
definePayloadReducer(reducer, reducers[reducer as keyof typeof reducers])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -96,7 +96,10 @@ interface Router {
|
||||
removeRoute: (name: string) => void
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
|
||||
export default defineNuxtPlugin<{ route: Route, router: Router }>({
|
||||
name: 'nuxt:router',
|
||||
enforce: 'pre',
|
||||
setup (nuxtApp) {
|
||||
const initialURL = process.client
|
||||
? withoutBase(window.location.pathname, useRuntimeConfig().app.baseURL) + window.location.search + window.location.hash
|
||||
: nuxtApp.ssrContext!.url
|
||||
@ -110,7 +113,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
|
||||
error: []
|
||||
}
|
||||
|
||||
const registerHook = <T extends keyof RouterHooks>(hook: T, guard: RouterHooks[T]) => {
|
||||
const registerHook = <T extends keyof RouterHooks> (hook: T, guard: RouterHooks[T]) => {
|
||||
hooks[hook].push(guard)
|
||||
return () => hooks[hook].splice(hooks[hook].indexOf(guard), 1)
|
||||
}
|
||||
@ -268,4 +271,5 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => {
|
||||
router
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -40,11 +40,14 @@ const components = ${genObjectFromRawEntries(globalComponents.map((c) => {
|
||||
return [c.pascalName, `defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))`]
|
||||
}))}
|
||||
|
||||
export default defineNuxtPlugin(nuxtApp => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:global-components',
|
||||
setup (nuxtApp) {
|
||||
for (const name in components) {
|
||||
nuxtApp.vueApp.component(name, components[name])
|
||||
nuxtApp.vueApp.component('Lazy' + name, components[name])
|
||||
}
|
||||
}
|
||||
})
|
||||
`
|
||||
}
|
||||
|
@ -292,9 +292,9 @@ async function initNuxt (nuxt: Nuxt) {
|
||||
|
||||
// Add experimental support for custom types in JSON payload
|
||||
if (nuxt.options.experimental.renderJsonPayloads) {
|
||||
nuxt.hook('modules:done', () => {
|
||||
nuxt.options.plugins.unshift(resolve(nuxt.options.appDir, 'plugins/revive-payload.client'))
|
||||
nuxt.options.plugins.unshift(resolve(nuxt.options.appDir, 'plugins/revive-payload.server'))
|
||||
nuxt.hooks.hook('modules:done', () => {
|
||||
addPlugin(resolve(nuxt.options.appDir, 'plugins/revive-payload.client'))
|
||||
addPlugin(resolve(nuxt.options.appDir, 'plugins/revive-payload.server'))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,9 @@ import { defineNuxtPlugin } from '#app/nuxt'
|
||||
// @ts-expect-error untyped
|
||||
import { appHead } from '#build/nuxt.config.mjs'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:head',
|
||||
setup (nuxtApp) {
|
||||
const createHead = process.server ? createServerHead : createClientHead
|
||||
const head = createHead()
|
||||
head.push(appHead)
|
||||
@ -38,4 +40,5 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -2,7 +2,10 @@
|
||||
import { polyfillAsVueUseHead } from '@unhead/vue/polyfill'
|
||||
import { defineNuxtPlugin } from '#app/nuxt'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:vueuse-head-polyfill',
|
||||
setup (nuxtApp) {
|
||||
// avoid breaking ecosystem dependencies using low-level @vueuse/head APIs
|
||||
polyfillAsVueUseHead(nuxtApp.vueApp._context.provides.usehead)
|
||||
}
|
||||
})
|
||||
|
@ -23,6 +23,7 @@ const appPreset = defineUnimportPreset({
|
||||
'defineNuxtComponent',
|
||||
'useNuxtApp',
|
||||
'defineNuxtPlugin',
|
||||
'definePayloadPlugin',
|
||||
'reloadNuxtApp',
|
||||
'useRuntimeConfig',
|
||||
'useState',
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { hasProtocol } from 'ufo'
|
||||
import { defineNuxtPlugin, useNuxtApp } from '#app/nuxt'
|
||||
import { defineNuxtPlugin } from '#app/nuxt'
|
||||
import { useRouter } from '#app/composables/router'
|
||||
// @ts-ignore
|
||||
import layouts from '#build/layouts'
|
||||
// @ts-ignore
|
||||
import { namedMiddleware } from '#build/middleware'
|
||||
|
||||
export default defineNuxtPlugin(() => {
|
||||
const nuxtApp = useNuxtApp()
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:prefetch',
|
||||
setup (nuxtApp) {
|
||||
const router = useRouter()
|
||||
|
||||
// Force layout prefetch on route changes
|
||||
@ -38,4 +39,5 @@ export default defineNuxtPlugin(() => {
|
||||
layouts[layout]()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -45,7 +45,10 @@ function createCurrentLocation (
|
||||
return path + search + hash
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin(async (nuxtApp) => {
|
||||
export default defineNuxtPlugin({
|
||||
name: 'nuxt:router',
|
||||
enforce: 'pre',
|
||||
async setup (nuxtApp) {
|
||||
let routerBase = useRuntimeConfig().app.baseURL
|
||||
if (routerOptions.hashMode && !routerBase.includes('#')) {
|
||||
// allow the user to provide a `#` in the middle: `/base/#/app`
|
||||
@ -198,4 +201,5 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
||||
})
|
||||
|
||||
return { provide: { router } }
|
||||
}
|
||||
}) as Plugin<{ router: Router }>
|
||||
|
@ -195,6 +195,7 @@ export default defineUntypedSchema({
|
||||
asyncFunctions: ['defineNuxtPlugin', 'defineNuxtRouteMiddleware'],
|
||||
objectDefinitions: {
|
||||
defineNuxtComponent: ['asyncData', 'setup'],
|
||||
defineNuxtPlugin: ['setup'],
|
||||
definePageMeta: ['middleware', 'validate']
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ describe.skipIf(isWindows || process.env.ECOSYSTEM_CI)('minimal nuxt application
|
||||
|
||||
it('default client bundle size', async () => {
|
||||
stats.client = await analyzeSizes('**/*.js', publicDir)
|
||||
expect(roundToKilobytes(stats.client.totalBytes)).toMatchInlineSnapshot('"104k"')
|
||||
expect(roundToKilobytes(stats.client.totalBytes)).toMatchInlineSnapshot('"105k"')
|
||||
expect(stats.client.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
|
||||
[
|
||||
"_nuxt/_plugin-vue_export-helper.js",
|
||||
@ -40,7 +40,7 @@ describe.skipIf(isWindows || process.env.ECOSYSTEM_CI)('minimal nuxt application
|
||||
|
||||
it('default server bundle size', async () => {
|
||||
stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
||||
expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"91k"')
|
||||
expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"92k"')
|
||||
|
||||
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
||||
expect(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"2650k"')
|
||||
|
6
test/fixtures/basic/nuxt.config.ts
vendored
6
test/fixtures/basic/nuxt.config.ts
vendored
@ -108,12 +108,6 @@ export default defineNuxtConfig({
|
||||
addVitePlugin(plugin.vite())
|
||||
addWebpackPlugin(plugin.webpack())
|
||||
},
|
||||
function (_options, nuxt) {
|
||||
// TODO: support directly via object syntax plugins: https://github.com/nuxt/nuxt/issues/14628
|
||||
nuxt.hook('modules:done', () => {
|
||||
nuxt.options.plugins.unshift('~/plugins/custom-type-registration')
|
||||
})
|
||||
},
|
||||
function (_options, nuxt) {
|
||||
const routesToDuplicate = ['/async-parent', '/fixed-keyed-child-parent', '/keyed-child-parent', '/with-layout', '/with-layout2']
|
||||
const stripLayout = (page: NuxtPage): NuxtPage => ({
|
||||
|
@ -1,4 +1,4 @@
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
export default definePayloadPlugin((nuxtApp) => {
|
||||
definePayloadReducer('BlinkingText', data => data === '<original-blink>' && '_')
|
||||
definePayloadReviver('BlinkingText', () => '<revivified-blink>')
|
||||
if (process.server) {
|
||||
|
Loading…
Reference in New Issue
Block a user