ssr:streamChunk Hook
The ssr:streamChunk hook runs inside renderSSRHeadSuspenseChunk(), once per chunk. It receives normalized copies of the tags from entries that were still pending after the shell went out. If no entries are pending, the chunk renderer returns early and the hook does not fire.
Hook Signature
export interface Hook {
'ssr:streamChunk': (ctx: { tags: HeadTag[] }) => SyncHookResult
}
type SyncHookResult = void
Parameters
| Name | Type | Description |
|---|---|---|
ctx.tags | HeadTag[] | Normalized copies of the tags from entries pending after the shell |
When It Fires
Inside renderSSRHeadSuspenseChunk() the hook runs after the pending entries are normalized. It runs before the renderer splits out streamed body tags, serializes the client patch, and clears the entries.
The client patch is built from the raw entry input, not from ctx.tags. The tags are copies for inspection. Changing them does not change what the client receives.
Only core normalization runs on these copies. Shapes that plugins own, such as _flatMeta or the legacy body prop, pass through as they are. If your listener needs them resolved, resolve them yourself.
Unlike the other SSR hooks, this one is typed void. The renderer does not wait for a returned promise before it serializes the patch and clears entries. Keep the listener synchronous.
Normalization only runs when a listener is registered. With no listener, the hook costs nothing.
Usage Example
import { defineHeadPlugin } from 'unhead/plugins'
export const pendingTagsPlugin = defineHeadPlugin({
key: 'pending-tags',
hooks: {
'ssr:streamChunk': ({ tags }) => {
for (const tag of tags)
console.log(`Tag arrived after the shell: ${tag.tag}`)
}
}
})
Crawler Visibility
Every tag this hook reports was missing from the initial shell. If a tag ends up in the client patch, the browser applies it with JavaScript, so crawlers that skip JavaScript never see it. Tags that qualify as streamed body tags are written into the HTML body instead and stay visible. See Streaming for which tags qualify.
ValidatePlugin uses this hook to report streamed-tag-hidden-from-bots during development.
For the initial render, use the ssr:rendered hook instead. It receives the serialized payload of the shell, not per-boundary patches.