Skip to content

Commit b2ca15d

Browse files
committedMar 13, 2025
fix(core): server template params missing from SSR payload
1 parent c7a4b78 commit b2ca15d

File tree

4 files changed

+46
-4
lines changed

4 files changed

+46
-4
lines changed
 

‎packages/unhead/src/plugins/templateParams.ts

+11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ export const TemplateParamsPlugin = /* @__PURE__ */ defineHeadPlugin((head) => {
1414
return {
1515
key: 'template-params',
1616
hooks: {
17+
'entries:normalize': (ctx) => {
18+
const params = ctx.tags.filter(t => t.tag === 'templateParams' && t.mode === 'server')?.[0]?.props || {}
19+
if (Object.keys(params).length) {
20+
head._ssrPayload = {
21+
templateParams: {
22+
...head._ssrPayload?.templateParams || {},
23+
...params,
24+
},
25+
}
26+
}
27+
},
1728
'tags:resolve': ({ tagMap, tags }) => {
1829
// we always process params so we can substitute the title
1930
const params = (tagMap.get('templateParams')?.props || {}) as TemplateParams

‎packages/unhead/src/server/createHead.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,22 @@ export function createHead<T = ResolvableHead>(options: CreateServerHeadOptions
3434
...(options.init || []),
3535
],
3636
})
37+
unhead._ssrPayload = {}
3738
unhead.use({
3839
key: 'server',
3940
hooks: {
4041
'tags:resolve': function (ctx) {
4142
const title = ctx.tagMap.get('title') as HeadTag | undefined
4243
const titleTemplate = ctx.tagMap.get('titleTemplate') as HeadTag | undefined
43-
const templateParams = ctx.tagMap.get('templateParams') as HeadTag | undefined
44-
const payload: ResolvableHead = {
44+
let payload: ResolvableHead = {
4545
title: title?.mode === 'server' ? unhead._title : undefined,
4646
titleTemplate: titleTemplate?.mode === 'server' ? unhead._titleTemplate : undefined,
47-
templateParams: templateParams?.mode === 'server' ? unhead._templateParams : undefined,
47+
}
48+
if (Object.keys(unhead._ssrPayload || {}).length > 0) {
49+
payload = {
50+
...unhead._ssrPayload,
51+
...payload,
52+
}
4853
}
4954
// filter non-values
5055
if (Object.values(payload).some(Boolean)) {

‎packages/unhead/src/types/head.ts

+4
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ export interface Unhead<Input = ResolvableHead> {
228228
* @internal
229229
*/
230230
_titleTemplate?: string
231+
/**
232+
* @internal
233+
*/
234+
_ssrPayload?: ResolvableHead
231235
}
232236

233237
export interface DomState {

‎packages/unhead/test/unit/server/templateParams.test.ts

+23-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,28 @@ import { renderSSRHead } from '../../../src/server'
55
import { createServerHeadWithContext } from '../../util'
66

77
describe('ssr templateParams', () => {
8+
it('payload merging', async () => {
9+
const head = createServerHeadWithContext({
10+
plugins: [TemplateParamsPlugin],
11+
})
12+
head.push({
13+
templateParams: {
14+
foo: 'bar',
15+
},
16+
}, {
17+
mode: 'server',
18+
})
19+
head.push({
20+
templateParams: {
21+
separator: 'x',
22+
},
23+
})
24+
const { headTags, htmlAttrs } = await renderSSRHead(head)
25+
26+
expect(htmlAttrs).toMatchInlineSnapshot(`""`)
27+
expect(headTags).toMatchInlineSnapshot(`"<script id="unhead:payload" type="application/json">{"templateParams":{"foo":"bar"}}</script>"`)
28+
})
29+
830
it('basic', async () => {
931
const head = createServerHeadWithContext({
1032
plugins: [TemplateParamsPlugin],
@@ -121,7 +143,7 @@ describe('ssr templateParams', () => {
121143

122144
expect(headTags).toMatchInlineSnapshot(`
123145
"<title>test | My Awesome Site</title>
124-
<script id="unhead:payload" type="application/json">{"title":"test","titleTemplate":"%s %separator %siteName","templateParams":{"siteName":"My Awesome Site","foo":"bar","pageTitle":"test"}}</script>"
146+
<script id="unhead:payload" type="application/json">{"templateParams":{"separator":"|","siteName":"My Awesome Site","foo":"bar"},"title":"test","titleTemplate":"%s %separator %siteName"}</script>"
125147
`)
126148
})
127149

0 commit comments

Comments
 (0)
Please sign in to comment.