]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(ssr): resolve teleports for stream render APIs
authorEvan You <yyx990803@gmail.com>
Tue, 17 May 2022 04:41:40 +0000 (12:41 +0800)
committerEvan You <yyx990803@gmail.com>
Tue, 17 May 2022 04:41:40 +0000 (12:41 +0800)
packages/server-renderer/__tests__/ssrTeleport.spec.ts
packages/server-renderer/src/renderToStream.ts
packages/server-renderer/src/renderToString.ts

index f26c903584af122246485965bd7d865d6019a283..af915168b3c5f3b3202f6231e5f365a2d93d313d 100644 (file)
@@ -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('<!--teleport start--><!--teleport end-->')
     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><!---->`)
+  })
 })
index 749fb54db24675318ebd658e3670b6ac54471cab..79484f9cffc292405441734f7d6d0484119cd21e 100644 (file)
@@ -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<T extends SimpleReadable>(
 
   Promise.resolve(renderComponentVNode(vnode))
     .then(buffer => unrollBuffer(buffer, stream))
+    .then(() => resolveTeleports(context))
     .then(() => stream.push(null))
     .catch(error => {
       stream.destroy(error)
index f35ee9d62d972a3e698105da54320feb81212481..2450b0a3acbc16c5b1b25f44562f04afe7274c59 100644 (file)
@@ -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) {