From ac335c7a075e159672c8d21d6bd333fe02c592eb Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 8 Sep 2022 16:13:48 +0100 Subject: [PATCH 1/6] fix(nuxt): track suspense status so we can share single state --- packages/nuxt/src/pages/runtime/page.ts | 12 +++----- packages/nuxt/src/pages/runtime/router.ts | 9 ++++++ playground/app.vue | 29 ++++++++++++++----- playground/pages/a.vue | 10 +++++++ playground/pages/b.vue | 11 +++++++ playground/pages/b/b1.vue | 9 ++++++ playground/pages/c.vue | 13 +++++++++ playground/pages/c/c1.vue | 9 ++++++ playground/pages/index.vue | 16 ++++++++++ playground/pages/sync.vue | 9 ++++++ playground/plugins/spy.ts | 5 ++++ test/basic.test.ts | 14 +++++++++ test/fixtures/basic/layouts/custom.vue | 5 ++++ test/fixtures/basic/pages/another-parent.vue | 8 +++++ .../basic/pages/another-parent/index.vue | 5 ++++ 15 files changed, 149 insertions(+), 15 deletions(-) create mode 100644 playground/pages/a.vue create mode 100644 playground/pages/b.vue create mode 100644 playground/pages/b/b1.vue create mode 100644 playground/pages/c.vue create mode 100644 playground/pages/c/c1.vue create mode 100644 playground/pages/index.vue create mode 100644 playground/pages/sync.vue create mode 100644 playground/plugins/spy.ts diff --git a/packages/nuxt/src/pages/runtime/page.ts b/packages/nuxt/src/pages/runtime/page.ts index 1254b8a43d3..7d83faf97cd 100644 --- a/packages/nuxt/src/pages/runtime/page.ts +++ b/packages/nuxt/src/pages/runtime/page.ts @@ -1,4 +1,4 @@ -import { computed, defineComponent, h, inject, provide, reactive, onMounted, nextTick, Suspense, Transition, KeepAliveProps, TransitionProps } from 'vue' +import { computed, defineComponent, h, provide, reactive, onMounted, nextTick, Suspense, Transition, KeepAliveProps, TransitionProps } from 'vue' import type { DefineComponent, VNode } from 'vue' import { RouteLocationNormalized, RouteLocationNormalizedLoaded, RouterView } from 'vue-router' import type { RouteLocation } from 'vue-router' @@ -9,8 +9,6 @@ import { _wrapIf } from '#app/components/utils' // @ts-ignore import { appPageTransition as defaultPageTransition, appKeepalive as defaultKeepaliveConfig } from '#build/nuxt.config.mjs' -const isNestedKey = Symbol('isNested') - export default defineComponent({ name: 'NuxtPage', inheritAttrs: false, @@ -37,9 +35,6 @@ export default defineComponent({ setup (props, { attrs }) { const nuxtApp = useNuxtApp() - const isNested = inject(isNestedKey, false) - provide(isNestedKey, true) - return () => { return h(RouterView, { name: props.name, route: props.route, ...attrs }, { default: (routeProps: RouterViewSlotProps) => { @@ -49,8 +44,9 @@ export default defineComponent({ const transitionProps = props.transition ?? routeProps.route.meta.pageTransition ?? (defaultPageTransition as TransitionProps) return _wrapIf(Transition, transitionProps, - wrapInKeepAlive(props.keepalive ?? routeProps.route.meta.keepalive ?? (defaultKeepaliveConfig as KeepAliveProps), isNested && nuxtApp.isHydrating - // Include route children in parent suspense + // If we're already wrapped in a page component that is in-transition + // we can piggy-back on its suspense so we resolve at the same time. + wrapInKeepAlive(props.keepalive ?? routeProps.route.meta.keepalive ?? (defaultKeepaliveConfig as KeepAliveProps), nuxtApp.isHydrating || nuxtApp.isResolvingSuspense ? h(Component, { key, routeProps, pageKey: key, hasTransition: !!transitionProps } as {}) : h(Suspense, { onPending: () => nuxtApp.callHook('page:start', routeProps.Component), diff --git a/packages/nuxt/src/pages/runtime/router.ts b/packages/nuxt/src/pages/runtime/router.ts index 03bc591227c..8e97233ef3b 100644 --- a/packages/nuxt/src/pages/runtime/router.ts +++ b/packages/nuxt/src/pages/runtime/router.ts @@ -76,6 +76,15 @@ export default defineNuxtPlugin(async (nuxtApp) => { }) nuxtApp.vueApp.use(router) + // Ensure we don't trigger multiple suspenses in page navigation + nuxtApp.isResolvingSuspense = true + nuxtApp.hook('page:start', () => { + nuxtApp.isResolvingSuspense = true + }) + nuxtApp.hook('page:finish', () => { + nuxtApp.isResolvingSuspense = false + }) + const previousRoute = shallowRef(router.currentRoute.value) router.afterEach((_to, from) => { previousRoute.value = from diff --git a/playground/app.vue b/playground/app.vue index c93a9dcaf5f..a0ca05a3358 100644 --- a/playground/app.vue +++ b/playground/app.vue @@ -1,12 +1,27 @@ - - - + diff --git a/playground/pages/a.vue b/playground/pages/a.vue new file mode 100644 index 00000000000..5207b454929 --- /dev/null +++ b/playground/pages/a.vue @@ -0,0 +1,10 @@ + + + diff --git a/playground/pages/b.vue b/playground/pages/b.vue new file mode 100644 index 00000000000..10565e17c5e --- /dev/null +++ b/playground/pages/b.vue @@ -0,0 +1,11 @@ + + + diff --git a/playground/pages/b/b1.vue b/playground/pages/b/b1.vue new file mode 100644 index 00000000000..585407ab152 --- /dev/null +++ b/playground/pages/b/b1.vue @@ -0,0 +1,9 @@ + + diff --git a/playground/pages/c.vue b/playground/pages/c.vue new file mode 100644 index 00000000000..e221fdf3721 --- /dev/null +++ b/playground/pages/c.vue @@ -0,0 +1,13 @@ + + + diff --git a/playground/pages/c/c1.vue b/playground/pages/c/c1.vue new file mode 100644 index 00000000000..702bdffd635 --- /dev/null +++ b/playground/pages/c/c1.vue @@ -0,0 +1,9 @@ + + diff --git a/playground/pages/index.vue b/playground/pages/index.vue new file mode 100644 index 00000000000..620708d3f82 --- /dev/null +++ b/playground/pages/index.vue @@ -0,0 +1,16 @@ + diff --git a/playground/pages/sync.vue b/playground/pages/sync.vue new file mode 100644 index 00000000000..7e57dd408c0 --- /dev/null +++ b/playground/pages/sync.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/plugins/spy.ts b/playground/plugins/spy.ts new file mode 100644 index 00000000000..cb62cc54460 --- /dev/null +++ b/playground/plugins/spy.ts @@ -0,0 +1,5 @@ +export default defineNuxtPlugin((nuxtApp) => { + nuxtApp.hooks.beforeEach((event) => { + console.log(event.name) + }) +}) diff --git a/test/basic.test.ts b/test/basic.test.ts index 9116bc51db8..2a6fc0e2134 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -410,6 +410,20 @@ describe('automatically keyed composables', () => { }) }) +describe('single suspense tree', () => { + it('should generate a single suspense tree on initial hydration', async () => { + const page = await createPage() + const logs: string[] = [] + page.on('console', (msg) => { + logs.push(msg.text()) + }) + await page.goto(url('/another-parent')) + await page.waitForLoadState('networkidle') + expect(logs.length).toBe(2) + expect(logs.every(log => log === 'isHydrating: true')) + }) +}) + describe.skipIf(process.env.NUXT_TEST_DEV || process.env.TEST_WITH_WEBPACK)('inlining component styles', () => { it('should inline styles', async () => { const html = await $fetch('/styles') diff --git a/test/fixtures/basic/layouts/custom.vue b/test/fixtures/basic/layouts/custom.vue index e7938d8f69d..053033dcbc0 100644 --- a/test/fixtures/basic/layouts/custom.vue +++ b/test/fixtures/basic/layouts/custom.vue @@ -4,3 +4,8 @@ + + diff --git a/test/fixtures/basic/pages/another-parent.vue b/test/fixtures/basic/pages/another-parent.vue index a71dcab8f2c..62a4ebd48e0 100644 --- a/test/fixtures/basic/pages/another-parent.vue +++ b/test/fixtures/basic/pages/another-parent.vue @@ -4,3 +4,11 @@ + + diff --git a/test/fixtures/basic/pages/another-parent/index.vue b/test/fixtures/basic/pages/another-parent/index.vue index ff5e465ebc2..4c1f843aef0 100644 --- a/test/fixtures/basic/pages/another-parent/index.vue +++ b/test/fixtures/basic/pages/another-parent/index.vue @@ -3,3 +3,8 @@ another-parent/index + + From 75d5616b10aa124ed6281c4be3281c1f5af5332a Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 9 Sep 2022 21:43:37 +0100 Subject: [PATCH 2/6] refactor: don't register app component globally --- packages/nuxt/src/app/components/nuxt-root.vue | 7 +++++-- packages/nuxt/src/app/entry.ts | 4 ---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/nuxt/src/app/components/nuxt-root.vue b/packages/nuxt/src/app/components/nuxt-root.vue index 173eddf9808..1f4225e790e 100644 --- a/packages/nuxt/src/app/components/nuxt-root.vue +++ b/packages/nuxt/src/app/components/nuxt-root.vue @@ -1,14 +1,17 @@ - From 3cf0fdeea8a84095fb5acce6e8bd5b125680c97f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 9 Sep 2022 23:06:47 +0100 Subject: [PATCH 4/6] fix: type check --- packages/nuxt/src/app/components/layout.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nuxt/src/app/components/layout.ts b/packages/nuxt/src/app/components/layout.ts index 7c8764d3e16..06f2a0e9a47 100644 --- a/packages/nuxt/src/app/components/layout.ts +++ b/packages/nuxt/src/app/components/layout.ts @@ -1,4 +1,4 @@ -import { computed, defineComponent, isRef, nextTick, h, onMounted, Ref, Transition, VNode } from 'vue' +import { computed, defineComponent, isRef, nextTick, h, onMounted, Ref, Transition, VNode, Component } from 'vue' import { _wrapIf } from './utils' import { useRoute } from '#app' // @ts-ignore @@ -25,7 +25,7 @@ const LayoutLoader = defineComponent({ }) } - const LayoutComponent = await layouts[props.name]().then(r => r.default || r) + const LayoutComponent = await layouts[props.name]().then((r: any) => r.default || r) return () => { if (process.dev && process.client && props.hasTransition) { From c829d9ddde9c42087b2f683822537a8ab24d1487 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sat, 10 Sep 2022 00:45:25 +0100 Subject: [PATCH 5/6] fix: remove unused type --- packages/nuxt/src/app/components/layout.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/app/components/layout.ts b/packages/nuxt/src/app/components/layout.ts index 06f2a0e9a47..47a025c1de1 100644 --- a/packages/nuxt/src/app/components/layout.ts +++ b/packages/nuxt/src/app/components/layout.ts @@ -1,4 +1,4 @@ -import { computed, defineComponent, isRef, nextTick, h, onMounted, Ref, Transition, VNode, Component } from 'vue' +import { computed, defineComponent, isRef, nextTick, h, onMounted, Ref, Transition, VNode } from 'vue' import { _wrapIf } from './utils' import { useRoute } from '#app' // @ts-ignore From f6140997a610ee929faf6c724e1bcb77531e4115 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 21 Sep 2022 14:18:42 +0100 Subject: [PATCH 6/6] chore: revert playground --- playground/app.vue | 29 +++++++---------------------- playground/pages/a.vue | 10 ---------- playground/pages/b.vue | 11 ----------- playground/pages/b/b1.vue | 9 --------- playground/pages/c.vue | 13 ------------- playground/pages/c/c1.vue | 9 --------- playground/pages/index.vue | 16 ---------------- playground/pages/sync.vue | 9 --------- playground/plugins/spy.ts | 5 ----- 9 files changed, 7 insertions(+), 104 deletions(-) delete mode 100644 playground/pages/a.vue delete mode 100644 playground/pages/b.vue delete mode 100644 playground/pages/b/b1.vue delete mode 100644 playground/pages/c.vue delete mode 100644 playground/pages/c/c1.vue delete mode 100644 playground/pages/index.vue delete mode 100644 playground/pages/sync.vue delete mode 100644 playground/plugins/spy.ts diff --git a/playground/app.vue b/playground/app.vue index a0ca05a3358..c93a9dcaf5f 100644 --- a/playground/app.vue +++ b/playground/app.vue @@ -1,27 +1,12 @@ + + - + diff --git a/playground/pages/a.vue b/playground/pages/a.vue deleted file mode 100644 index 5207b454929..00000000000 --- a/playground/pages/a.vue +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/playground/pages/b.vue b/playground/pages/b.vue deleted file mode 100644 index 10565e17c5e..00000000000 --- a/playground/pages/b.vue +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/playground/pages/b/b1.vue b/playground/pages/b/b1.vue deleted file mode 100644 index 585407ab152..00000000000 --- a/playground/pages/b/b1.vue +++ /dev/null @@ -1,9 +0,0 @@ - - diff --git a/playground/pages/c.vue b/playground/pages/c.vue deleted file mode 100644 index e221fdf3721..00000000000 --- a/playground/pages/c.vue +++ /dev/null @@ -1,13 +0,0 @@ - - - diff --git a/playground/pages/c/c1.vue b/playground/pages/c/c1.vue deleted file mode 100644 index 702bdffd635..00000000000 --- a/playground/pages/c/c1.vue +++ /dev/null @@ -1,9 +0,0 @@ - - diff --git a/playground/pages/index.vue b/playground/pages/index.vue deleted file mode 100644 index 620708d3f82..00000000000 --- a/playground/pages/index.vue +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/playground/pages/sync.vue b/playground/pages/sync.vue deleted file mode 100644 index 7e57dd408c0..00000000000 --- a/playground/pages/sync.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/playground/plugins/spy.ts b/playground/plugins/spy.ts deleted file mode 100644 index cb62cc54460..00000000000 --- a/playground/plugins/spy.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default defineNuxtPlugin((nuxtApp) => { - nuxtApp.hooks.beforeEach((event) => { - console.log(event.name) - }) -})