fix(nuxt): provide global scope for nuxt plugin context (#23667)

This commit is contained in:
Daniel Roe 2023-10-15 15:52:46 +01:00 committed by GitHub
parent 5c7cca170a
commit 1487c5631a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 11 additions and 6 deletions

View File

@ -1,4 +1,4 @@
import { getCurrentInstance, hasInjectionContext, inject, onUnmounted } from 'vue' import { getCurrentInstance, hasInjectionContext, inject, onScopeDispose } from 'vue'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import type { NavigationFailure, NavigationGuard, RouteLocationNormalized, RouteLocationPathRaw, RouteLocationRaw, Router, useRoute as _useRoute, useRouter as _useRouter } from '#vue-router' import type { NavigationFailure, NavigationGuard, RouteLocationNormalized, RouteLocationPathRaw, RouteLocationRaw, Router, useRoute as _useRoute, useRouter as _useRouter } from '#vue-router'
import { sanitizeStatusCode } from 'h3' import { sanitizeStatusCode } from 'h3'
@ -30,12 +30,12 @@ export const onBeforeRouteLeave = (guard: NavigationGuard) => {
if (to === from) { return } if (to === from) { return }
return guard(to, from, next) return guard(to, from, next)
}) })
onUnmounted(unsubscribe) onScopeDispose(unsubscribe)
} }
export const onBeforeRouteUpdate = (guard: NavigationGuard) => { export const onBeforeRouteUpdate = (guard: NavigationGuard) => {
const unsubscribe = useRouter().beforeEach(guard) const unsubscribe = useRouter().beforeEach(guard)
onUnmounted(unsubscribe) onScopeDispose(unsubscribe)
} }
export interface RouteMiddleware { export interface RouteMiddleware {
@ -182,6 +182,8 @@ export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: Na
// Client-side redirection using vue-router // Client-side redirection using vue-router
if (isExternal) { if (isExternal) {
// Run any cleanup steps for the current scope, like ending BroadcastChannel
nuxtApp._scope.stop()
if (options?.replace) { if (options?.replace) {
location.replace(toPath) location.replace(toPath)
} else { } else {

View File

@ -1,6 +1,6 @@
/* eslint-disable no-use-before-define */ /* eslint-disable no-use-before-define */
import { getCurrentInstance, hasInjectionContext, reactive } from 'vue' import { effectScope, getCurrentInstance, hasInjectionContext, reactive } from 'vue'
import type { App, Ref, VNode, onErrorCaptured } from 'vue' import type { App, EffectScope, Ref, VNode, onErrorCaptured } from 'vue'
import type { RouteLocationNormalizedLoaded } from '#vue-router' import type { RouteLocationNormalizedLoaded } from '#vue-router'
import type { HookCallback, Hookable } from 'hookable' import type { HookCallback, Hookable } from 'hookable'
import { createHooks } from 'hookable' import { createHooks } from 'hookable'
@ -98,6 +98,8 @@ interface _NuxtApp {
[key: string]: unknown [key: string]: unknown
/** @internal */
_scope: EffectScope
/** @internal */ /** @internal */
_asyncDataPromises: Record<string, Promise<any> | undefined> _asyncDataPromises: Record<string, Promise<any> | undefined>
/** @internal */ /** @internal */
@ -202,6 +204,7 @@ export interface CreateOptions {
export function createNuxtApp (options: CreateOptions) { export function createNuxtApp (options: CreateOptions) {
let hydratingCount = 0 let hydratingCount = 0
const nuxtApp: NuxtApp = { const nuxtApp: NuxtApp = {
_scope: effectScope(),
provide: undefined, provide: undefined,
globalName: 'nuxt', globalName: 'nuxt',
versions: { versions: {
@ -217,7 +220,7 @@ export function createNuxtApp (options: CreateOptions) {
static: { static: {
data: {} data: {}
}, },
runWithContext: (fn: any) => callWithNuxt(nuxtApp, fn), runWithContext: (fn: any) => nuxtApp._scope.run(() => callWithNuxt(nuxtApp, fn)),
isHydrating: import.meta.client, isHydrating: import.meta.client,
deferHydration () { deferHydration () {
if (!nuxtApp.isHydrating) { return () => {} } if (!nuxtApp.isHydrating) { return () => {} }