Subscribe on changes!

renderToString doesn't render Component is script (json ld)

avatar
Nov 18th 2022

Vue version

3.2.45

Link to minimal reproduction

https://github.com/yooouuri/render-to-string-script-tag

import { createSSRApp } from 'vue'
import { renderToString } from 'vue/server-renderer'

const app = createSSRApp({
  template: `<Component :is="'script'" data-something="value" v-html="JSON.stringify({ foo: 'bar' })" />`,
})

renderToString(app).then(html => console.log(html))

Steps to reproduce

Clone the minimal reproduction repo

git clone https://github.com/yooouuri/render-to-string-script-tag
yarn
node index.js

What is expected?

After running node index.js

<script data-something="value">{"foo":"bar"}</script>

What is actually happening?

But It logs

<script data-something="value"></script>

The following playground https://sfc.vuejs.org/#eNpNj71uwzAMhF9F4OIWqKVdcAsU3Tq0Q1ctSkrHCqwfiLSDwPC7hwoyZCPvI+6OG3yWotcFwcLAGMvsGT9cUmr4yrHkhImVDfTuoKNjDYU7B+rfs+8pR+QppJOw1c8LClj7ieMswvff748mroLDeH3Z1JizVd3B107tr3JpJGQwT4nwBkECK/fRF32mnKTS1pq4ByAHVt2VpknntjuYmAtZY2g8tkfOpHM9GZl0XRKHiBop9oeaL4RVjB00i92lHfYbAJZWgA==

Logs what I would expect

image

System Info

System:
    OS: macOS 12.4
    CPU: (8) arm64 Apple M1 Pro
    Memory: 110.16 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.18.0 - /opt/homebrew/opt/node@16/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 8.19.2 - /opt/homebrew/opt/node@16/bin/npm
  Browsers:
    Firefox: 107.0
    Safari: 15.5
  npmPackages:
    vue: ^3.2.45 => 3.2.45

Any additional comments?

No response

avatar
Nov 19th 2022
image I don't think this syntax is allowed in JavaScript. It is equivalent to the following code:
<script>"foo": "bar"</script>
avatar
Nov 23rd 2022

@zhangzhonghe I forgot something to mention...

Im trying to render a json-ld script.

Updated playground: https://sfc.vuejs.org/#eNp9jz9PwzAQxb+KdUtANPZuBSTExgADqxc3vbSu4j86X4OqKN+dM2KoQGK7e+/0e+9WeC5FLxcECwNjLLNnfHJJqeElx5ITJlY21EcHXR0pFO4cKL4WFMWXMofRc8jJzIeHc81JzKU/cZzFfv14f9OVKaRjmK53q5pytqrbe+rUdi+XRoIGc5MKOwgSStxHX3TjSa21tXE/RnVg1bfSNOnddgcn5lKtMXUa2zPnqjMdjUyaLolDRI019nvKnxVJwA52Nwwj4oLUE6YDEtJ/zF+nf7gNu7m0wfYFBJJ3Ow==

<Component :is="'script'" type="application/ld+json" v-html="JSON.stringify({ foo: 'bar' })" />

Gives me:

image

So in a SFC it works as expected.

And when I use the renderToString method (used when in SSR mode)

import { createSSRApp } from 'vue'
import { renderToString } from 'vue/server-renderer'

const app = createSSRApp({
  template: `<Component :is="'script'" type="application/ld+json" v-html="JSON.stringify({ foo: 'bar' })" />`,
})

renderToString(app).then(html => console.log(html))

It logs

image

So there is a difference between client side rendering and SSR.

avatar
Nov 28th 2022

https://github.com/vuejs/core/blob/121eb32fb0a21cf9988d788cfad1b4249b15997b/packages/server-renderer/src/helpers/ssrRenderAttrs.ts#L14-L17

we ignore innerHTML tag in SSR.

duplicate of #6435 The root cause is that directives with children overwrite (e.g. v-html & v-text) are not working with Component yet in SSR. Close this one.

a workaround:

<script>
import { h } from 'vue'
export default {
  setup(props) {
    return () =>
      h('script', {
          type: "application/ld+json",
        innerHTML: JSON.stringify({ foo: 'bar' }),
      });
  },
}
</script>
avatar
Nov 28th 2022

@edison1105

Removed the innerHTML key.

image

Build Vue locally, used locally build @vue/server-renderer.

Sadly doesn't work.

image