From 77fef9734496abe1e842d8e4086c497656d1fab2 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 17 May 2022 12:41:40 +0800 Subject: [PATCH] fix(ssr): resolve teleports for stream render APIs --- .../__tests__/ssrTeleport.spec.ts | 34 +++++++++++++++++++ .../server-renderer/src/renderToStream.ts | 2 ++ .../server-renderer/src/renderToString.ts | 2 +- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/packages/server-renderer/__tests__/ssrTeleport.spec.ts b/packages/server-renderer/__tests__/ssrTeleport.spec.ts index f26c9035..af915168 100644 --- a/packages/server-renderer/__tests__/ssrTeleport.spec.ts +++ b/packages/server-renderer/__tests__/ssrTeleport.spec.ts @@ -4,6 +4,7 @@ import { createApp, h, Teleport } from 'vue' import { renderToString } from '../src/renderToString' +import { renderToSimpleStream } from '../src/renderToStream' import { SSRContext } from '../src/render' import { ssrRenderTeleport } from '../src/helpers/ssrRenderTeleport' @@ -134,4 +135,37 @@ describe('ssrRenderTeleport', () => { expect(html).toBe('') expect(ctx.teleports!['#target']).toBe(`
content
`) }) + + test('teleport inside async component (stream)', async () => { + const ctx: SSRContext = {} + const asyncComponent = { + template: '
content
', + async setup() {} + } + let html = '' + let resolve: any + const p = new Promise(r => (resolve = r)) + renderToSimpleStream( + h({ + template: '', + components: { asyncComponent } + }), + ctx, + { + push(chunk) { + if (chunk === null) { + resolve() + } else { + html += chunk + } + }, + destroy(err) { + throw err + } + } + ) + await p + expect(html).toBe('') + expect(ctx.teleports!['#target']).toBe(`
content
`) + }) }) diff --git a/packages/server-renderer/src/renderToStream.ts b/packages/server-renderer/src/renderToStream.ts index 749fb54d..79484f9c 100644 --- a/packages/server-renderer/src/renderToStream.ts +++ b/packages/server-renderer/src/renderToStream.ts @@ -9,6 +9,7 @@ import { import { isString, isPromise } from '@vue/shared' import { renderComponentVNode, SSRBuffer, SSRContext } from './render' import { Readable, Writable } from 'stream' +import { resolveTeleports } from './renderToString' const { isVNode } = ssrUtils @@ -74,6 +75,7 @@ export function renderToSimpleStream( Promise.resolve(renderComponentVNode(vnode)) .then(buffer => unrollBuffer(buffer, stream)) + .then(() => resolveTeleports(context)) .then(() => stream.push(null)) .catch(error => { stream.destroy(error) diff --git a/packages/server-renderer/src/renderToString.ts b/packages/server-renderer/src/renderToString.ts index f35ee9d6..2450b0a3 100644 --- a/packages/server-renderer/src/renderToString.ts +++ b/packages/server-renderer/src/renderToString.ts @@ -70,7 +70,7 @@ export async function renderToString( return result } -async function resolveTeleports(context: SSRContext) { +export async function resolveTeleports(context: SSRContext) { if (context.__teleportBuffers) { context.teleports = context.teleports || {} for (const key in context.__teleportBuffers) {