fix(ssr): resolve teleports for stream render APIs
This commit is contained in:
parent
57d3a0566f
commit
77fef97344
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
import { createApp, h, Teleport } from 'vue'
|
import { createApp, h, Teleport } from 'vue'
|
||||||
import { renderToString } from '../src/renderToString'
|
import { renderToString } from '../src/renderToString'
|
||||||
|
import { renderToSimpleStream } from '../src/renderToStream'
|
||||||
import { SSRContext } from '../src/render'
|
import { SSRContext } from '../src/render'
|
||||||
import { ssrRenderTeleport } from '../src/helpers/ssrRenderTeleport'
|
import { ssrRenderTeleport } from '../src/helpers/ssrRenderTeleport'
|
||||||
|
|
||||||
@ -134,4 +135,37 @@ describe('ssrRenderTeleport', () => {
|
|||||||
expect(html).toBe('<!--teleport start--><!--teleport end-->')
|
expect(html).toBe('<!--teleport start--><!--teleport end-->')
|
||||||
expect(ctx.teleports!['#target']).toBe(`<div>content</div><!---->`)
|
expect(ctx.teleports!['#target']).toBe(`<div>content</div><!---->`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('teleport inside async component (stream)', async () => {
|
||||||
|
const ctx: SSRContext = {}
|
||||||
|
const asyncComponent = {
|
||||||
|
template: '<teleport to="#target"><div>content</div></teleport>',
|
||||||
|
async setup() {}
|
||||||
|
}
|
||||||
|
let html = ''
|
||||||
|
let resolve: any
|
||||||
|
const p = new Promise(r => (resolve = r))
|
||||||
|
renderToSimpleStream(
|
||||||
|
h({
|
||||||
|
template: '<async-component />',
|
||||||
|
components: { asyncComponent }
|
||||||
|
}),
|
||||||
|
ctx,
|
||||||
|
{
|
||||||
|
push(chunk) {
|
||||||
|
if (chunk === null) {
|
||||||
|
resolve()
|
||||||
|
} else {
|
||||||
|
html += chunk
|
||||||
|
}
|
||||||
|
},
|
||||||
|
destroy(err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await p
|
||||||
|
expect(html).toBe('<!--teleport start--><!--teleport end-->')
|
||||||
|
expect(ctx.teleports!['#target']).toBe(`<div>content</div><!---->`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
import { isString, isPromise } from '@vue/shared'
|
import { isString, isPromise } from '@vue/shared'
|
||||||
import { renderComponentVNode, SSRBuffer, SSRContext } from './render'
|
import { renderComponentVNode, SSRBuffer, SSRContext } from './render'
|
||||||
import { Readable, Writable } from 'stream'
|
import { Readable, Writable } from 'stream'
|
||||||
|
import { resolveTeleports } from './renderToString'
|
||||||
|
|
||||||
const { isVNode } = ssrUtils
|
const { isVNode } = ssrUtils
|
||||||
|
|
||||||
@ -74,6 +75,7 @@ export function renderToSimpleStream<T extends SimpleReadable>(
|
|||||||
|
|
||||||
Promise.resolve(renderComponentVNode(vnode))
|
Promise.resolve(renderComponentVNode(vnode))
|
||||||
.then(buffer => unrollBuffer(buffer, stream))
|
.then(buffer => unrollBuffer(buffer, stream))
|
||||||
|
.then(() => resolveTeleports(context))
|
||||||
.then(() => stream.push(null))
|
.then(() => stream.push(null))
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
stream.destroy(error)
|
stream.destroy(error)
|
||||||
|
@ -70,7 +70,7 @@ export async function renderToString(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resolveTeleports(context: SSRContext) {
|
export async function resolveTeleports(context: SSRContext) {
|
||||||
if (context.__teleportBuffers) {
|
if (context.__teleportBuffers) {
|
||||||
context.teleports = context.teleports || {}
|
context.teleports = context.teleports || {}
|
||||||
for (const key in context.__teleportBuffers) {
|
for (const key in context.__teleportBuffers) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user