fix(nuxt): handle async children in ClientFallback (#24086)

This commit is contained in:
webfansplz 2023-11-04 05:04:26 +08:00 committed by GitHub
parent 6c48f8b8e6
commit ea3ce937e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 42 additions and 3 deletions

View File

@ -1,6 +1,9 @@
import { defineComponent, getCurrentInstance, onErrorCaptured, ref } from 'vue'
import { ssrRenderAttrs, ssrRenderSlot, ssrRenderVNode } from 'vue/server-renderer'
// eslint-disable-next-line
import { isPromise } from '@vue/shared'
import { useState } from '../composables/state'
import { useNuxtApp } from '../nuxt'
import { createBuffer } from './utils'
const NuxtClientFallbackServer = defineComponent({
@ -34,9 +37,10 @@ const NuxtClientFallbackServer = defineComponent({
return true
}
},
setup (props, ctx) {
async setup (props, ctx) {
const vm = getCurrentInstance()
const ssrFailed = ref(false)
const nuxtApp = useNuxtApp()
onErrorCaptured((err) => {
useState(`${props.uid}`, () => true)
@ -53,10 +57,15 @@ const NuxtClientFallbackServer = defineComponent({
ssrRenderVNode(ssrVNodes.push, defaultSlot![i], vm!)
}
const buffer = ssrVNodes.getBuffer()
if (buffer.hasAsync) {
await Promise.all(buffer.filter(isPromise))
}
return { ssrFailed, ssrVNodes }
} catch (ssrError) {
// catch in dev
useState(`${props.uid}`, () => true)
nuxtApp.runWithContext(() => useState(`${props.uid}`, () => true))
ctx.emit('ssr-error', ssrError)
return { ssrFailed: true, ssrVNodes: [] }
}

View File

@ -424,7 +424,8 @@ describe('pages', () => {
'clientfallback-non-stateful-setup',
'clientfallback-non-stateful',
'clientfallback-stateful-setup',
'clientfallback-stateful'
'clientfallback-stateful',
'clientfallback-async-setup'
]
const html = await $fetch('/client-fallback')
// ensure failed components are not rendered server-side
@ -441,6 +442,9 @@ describe('pages', () => {
expect(html).not.toContain('<p></p>')
expect(html).toContain('hi')
// aysnc setup
expect(html).toContain('Work with async setup')
const { page, pageErrors } = await renderPage('/client-fallback')
// ensure components reactivity once mounted
await page.locator('#increment-count').click()

View File

@ -0,0 +1,14 @@
<script setup>
async function getData () { }
await getData()
// break server-side
const data = window.__NUXT__
</script>
<template>
<div>
This breaks in server-side async setup. {{ data.serverRendered }}
</div>
</template>

View File

@ -0,0 +1,11 @@
<template>
<div>
async setup
<NuxtClientFallback>
<BreakInAsyncSetup class="clientfallback-async-setup" />
<template #fallback>
<div>Work with async setup</div>
</template>
</NuxtClientFallback>
</div>
</template>

View File

@ -38,6 +38,7 @@
<ClientFallbackStatefulSetup />
<ClientFallbackNonStatefulSetup />
<ClientFallbackNonStateful />
<ClientFallbackAsyncSetup />
<NuxtClientFallback keep-fallback>
<div>
<BreakInSetup />