Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

headTags are empty when using pipeToWebWritable #27

Closed
daliborgogic opened this issue Nov 28, 2022 · 6 comments
Closed

headTags are empty when using pipeToWebWritable #27

daliborgogic opened this issue Nov 28, 2022 · 6 comments

Comments

@daliborgogic
Copy link

daliborgogic commented Nov 28, 2022

import { createHead, useHead } from '@unhead/vue'
import { createSSRApp, ref } from 'vue'
import { pipeToWebWritable } from '@vue/server-renderer'
import { renderSSRHead } from '@unhead/ssr'
import { describe, it, expect } from 'vitest'

const template = String.raw`<!doctype html><html lang="en"><!--head--><div id="app"><!--app--></div></html>`

describe('vue ssr', () => {
  it('pipeToWebWritable', async () => {
    const head = createHead()
    const app = createSSRApp({
      async setup() {
        const title = ref('initial title')
        useHead({
          title,
        })
        await new Promise(resolve => setTimeout(resolve, 200))
        title.value = 'new title'
        return () => '<div>hi</div>'
      },
    })
    app.use(head)

    const [prepend, append] = template.split('<!--app-->')
    const { headTags } = await renderSSRHead(head)
    const encoder = new TextEncoder()

    const { writable } = new TransformStream({
      start(controller) {
        // prepend.replace('<!--head-->', headTags)
        controller.enqueue(encoder.encode(prepend))
      },
      flush(controller) {
        controller.enqueue(encoder.encode(append))
      }
    })

    pipeToWebWritable(app, {}, writable)

    expect(headTags).eq('<title>new title</title>')
  })
})
 ❯ test/stream.test.js:29:22
     27|     await pipeToWebWritable(app, {}, writable)
     28| 
     29|     expect(headTags).eq('<title>new title</title>')
       |                      ^
     30|   })
     31| })
-    Expected   "<title>new title</title>"
+    Received   ""
@daliborgogic daliborgogic changed the title Headtags are empty when using pipeToWebWritable headTags are empty when using pipeToWebWritable Nov 28, 2022
@harlan-zw
Copy link
Collaborator

Hey @daliborgogic

Thanks for the issue.

I'm not entirely sure how to solve this, as head tags are written as the Vue app is rendered. Do you have any ideas?

@harlan-zw harlan-zw changed the title headTags are empty when using pipeToWebWritable headTags are empty when using pipeToWebWritable Dec 1, 2022
@daliborgogic
Copy link
Author

@harlan-zw For now no idea. Will check what we can and what we can with hooks. You can close this issue. If we found a solution we will make a PR.

@bukandicki
Copy link

have you tried this code @daliborgogic @harlan-zw ?

const appHtml = await renderToString(app);
const { headTags } = await renderSSRHead(head);

I had the same case, then I was able to solve it by changing the order, first renderToString then renderSSRRHead

@harlan-zw
Copy link
Collaborator

harlan-zw commented Dec 27, 2022

Isn't that just regular SSR? My understanding of the Vue rendering stream is that it's sending chunks as they are rendered so the head data would need to be appended as it's rendered, which it isn't for performance reasons.

@daliborgogic
Copy link
Author

daliborgogic commented Apr 10, 2023

@harlan-zw yes, it's regular SSR. You are right. Workaround until there is a better way

- const { headTags } = await renderSSRHead(head)
+ const decoder = new TextDecoder()
+ let c
+ let once = false
  const { readable, writable } = new TransformStream({
-   start() {/**/},
+   async transform(chunk, controller) {     
+     if (!once) {
+      const decodedChunk = decoder.decode(chunk)
+      const { headTags } = await renderSSRHead(head)
+      const replacedHead = prepend.replace(`<!--head-->`, headTags)
+      const encodedChunk = encoder.encode(replacedHead + decodedChunk)
+      c = encodedChunk
+      once = true 
+     } else {
+       c = chunk
+     }
+     controller.enqueue(c)
+   },
    flush(controller) {
      controller.enqueue(encoder.encode(append))
    }
  })

@harlan-zw harlan-zw reopened this Apr 11, 2023
@harlan-zw harlan-zw mentioned this issue Sep 7, 2024
1 task
@harlan-zw
Copy link
Collaborator

Going to track here #396 which is part of the v2 roadmap.

@harlan-zw harlan-zw closed this as not planned Won't fix, can't repro, duplicate, stale Sep 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants