Skip to content

Commit 214f9ed

Browse files
authoredFeb 26, 2025··
fix(core,vue): deprecate server composables (#505)
* fix(core,vue): deprecate server composables * doc: alert * chore: build * chore: build
1 parent 2e36c2a commit 214f9ed

File tree

11 files changed

+144
-5
lines changed

11 files changed

+144
-5
lines changed
 

‎docs/7.api/2.use-server-head.md ‎docs/7.api/6.use-server-head.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
---
22
title: useServerHead()
33
description: Learn how to use server only tags.
4+
deprecated: true
45
---
56

7+
:UAlert{color="warning" variant="outline" title="Deprecated" description="The useServerHead composable is deprecated. Learn more at https://github.com/unjs/unhead/pull/505"}
8+
69
The `useServerHead` offers the same API as `useHead` but only works on the server.
710

811
```ts

‎packages/react/src/autoImports.ts

-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,5 @@ export const hookImports = {
44
'useHead',
55
'useSeoMeta',
66
'useHeadSafe',
7-
'useServerHead',
87
],
98
}

‎packages/solid-js/src/autoImports.ts

-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,5 @@ export const hookImports = {
44
'useHead',
55
'useSeoMeta',
66
'useHeadSafe',
7-
'useServerHead',
87
],
98
}

‎packages/svelte/src/autoImports.ts

-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,5 @@ export const autoImports = {
44
'useHead',
55
'useSeoMeta',
66
'useHeadSafe',
7-
'useServerHead',
87
],
98
}

‎packages/unhead/src/composables.ts

+24
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,28 @@ export function useSeoMeta<T extends Unhead<any>>(unhead: T, input: UseSeoMetaIn
4343
return entry
4444
}
4545

46+
/**
47+
* @deprecated use `useHead` instead. Advanced use cases should tree shake using import.meta.* if statements.
48+
*/
49+
export function useServerHead<T extends Unhead<any>>(unhead: T, input: Parameters<T['push']>[0] = {}, options: Omit<HeadEntryOptions, 'mode'> = {}): ReturnType<T['push']> {
50+
(options as HeadEntryOptions).mode = 'server'
51+
return unhead.push(input, options) as ReturnType<T['push']>
52+
}
53+
54+
/**
55+
* @deprecated use `useHeadSafe` instead. Advanced use cases should tree shake using import.meta.* if statements.
56+
*/
57+
export function useServerHeadSafe<T extends Unhead<any>>(unhead: T, input: HeadSafe = {}, options: Omit<HeadEntryOptions, 'mode'> = {}): ActiveHeadEntry<HeadSafe> {
58+
(options as HeadEntryOptions).mode = 'server'
59+
return useHeadSafe(unhead, input, { ...options, mode: 'server' })
60+
}
61+
62+
/**
63+
* @deprecated use `useSeoMeta` instead. Advanced use cases should tree shake using import.meta.* if statements.
64+
*/
65+
export function useServerSeoMeta<T extends Unhead<any>>(unhead: T, input: UseSeoMetaInput = {}, options?: Omit<HeadEntryOptions, 'mode'>): ActiveHeadEntry<UseSeoMetaInput> {
66+
(options as HeadEntryOptions).mode = 'server'
67+
return useSeoMeta(unhead, input, { ...options, mode: 'server' })
68+
}
69+
4670
export { useScript } from './scripts'

‎packages/unhead/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export { useHead, useHeadSafe, useScript, useSeoMeta } from './composables'
1+
export { useHead, useHeadSafe, useScript, useSeoMeta, useServerHead, useServerHeadSafe, useServerSeoMeta } from './composables'
22
export { createHeadCore } from './createHead'

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function createHead<T = Head>(options: CreateServerHeadOptions = {}) {
4141
const title = ctx.tagMap.get('title') as HeadTag | undefined
4242
const titleTemplate = ctx.tagMap.get('titleTemplate') as HeadTag | undefined
4343
const templateParams = ctx.tagMap.get('templateParams') as HeadTag | undefined
44-
const payload = {
44+
const payload: Head = {
4545
title: title?.mode === 'server' ? unhead._title : undefined,
4646
titleTemplate: titleTemplate?.mode === 'server' ? unhead._titleTemplate : undefined,
4747
templateParams: templateParams?.mode === 'server' ? unhead._templateParams : undefined,

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

+3
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ export interface CreateClientHeadOptions extends CreateHeadOptions {
139139
}
140140

141141
export interface HeadEntryOptions extends TagPosition, TagPriority, ProcessesTemplateParams, ResolvesDuplicates {
142+
/**
143+
* @deprecated Tree shaking should now be handled using import.meta.* if statements.
144+
*/
142145
mode?: RuntimeMode
143146
head?: Unhead
144147
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { useHead, useSeoMeta } from 'unhead'
2+
import { renderDOMHead } from 'unhead/client'
3+
import { renderSSRHead } from 'unhead/server'
4+
import { describe, it } from 'vitest'
5+
import { createClientHeadWithContext, createServerHeadWithContext, useDom } from '../../util'
6+
7+
describe('unhead e2e useServerSeoMeta', () => {
8+
it('useServerSeoMeta', async () => {
9+
// scenario: we are injecting root head schema which will not have a hydration step,
10+
// but we are also injecting a child head schema which will have a hydration step
11+
const ssrHead = createServerHeadWithContext()
12+
useSeoMeta(ssrHead, {
13+
title: 'title from nuxt.config.ts',
14+
description: 'Description from nuxt.config.ts',
15+
}, {
16+
tagPriority: 'low',
17+
})
18+
useHead(ssrHead, {
19+
htmlAttrs: { lang: 'nuxt.config' },
20+
script: [
21+
{
22+
innerHTML: 'lorem ipsum generate more lorem ipsum',
23+
},
24+
],
25+
}, {
26+
mode: 'server',
27+
})
28+
// i.e App.vue
29+
useSeoMeta(ssrHead, {
30+
title: 'title mainpage',
31+
description: 'description mainpage',
32+
}, {
33+
mode: 'server',
34+
})
35+
useHead(ssrHead, {
36+
htmlAttrs: { lang: 'app.vue' },
37+
}, {
38+
mode: 'server',
39+
})
40+
41+
const data = await renderSSRHead(ssrHead)
42+
43+
expect(data).toMatchInlineSnapshot(`
44+
{
45+
"bodyAttrs": "",
46+
"bodyTags": "",
47+
"bodyTagsOpen": "",
48+
"headTags": "<title>title mainpage</title>
49+
<script>lorem ipsum generate more lorem ipsum</script>
50+
<meta name="description" content="description mainpage">
51+
<script id="unhead:payload" type="application/json">{"title":"title mainpage"}</script>",
52+
"htmlAttrs": " lang="app.vue"",
53+
}
54+
`)
55+
56+
const dom = useDom(data)
57+
58+
const csrHead = createClientHeadWithContext({
59+
document: dom.window.document,
60+
})
61+
useHead(ssrHead, {
62+
htmlAttrs: { lang: 'nuxt.config' },
63+
}, {
64+
tagPriority: 'low',
65+
})
66+
useSeoMeta(csrHead, {
67+
title: 'Some cool reproduction repo :)',
68+
description: 'Description from nuxt.config.ts',
69+
}, {
70+
tagPriority: 'low',
71+
})
72+
73+
await renderDOMHead(csrHead, { document: dom.window.document })
74+
75+
expect(dom.serialize()).toMatchInlineSnapshot(`
76+
"<!DOCTYPE html><html lang="app.vue"><head>
77+
<title>title mainpage</title>
78+
<script>lorem ipsum generate more lorem ipsum</script>
79+
<meta name="description" content="Description from nuxt.config.ts">
80+
<script id="unhead:payload" type="application/json">{"title":"title mainpage"}</script>
81+
</head>
82+
<body>
83+
84+
<div>
85+
<h1>hello world</h1>
86+
</div>
87+
88+
89+
90+
</body></html>"
91+
`)
92+
})
93+
})

‎packages/vue/src/composables.ts

+10
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,24 @@ export function useSeoMeta(input: UseSeoMetaInput = {}, options: UseHeadOptions
8686
_flatMeta: meta,
8787
}, options)
8888
}
89+
90+
/**
91+
* @deprecated use `useHead` instead.Advanced use cases should tree shake using import.meta.* if statements.
92+
*/
8993
export function useServerHead<T extends MergeHead>(input: UseHeadInput<T> = {}, options: UseHeadOptions = {}): ActiveHeadEntry<any> {
9094
return useHead<T>(input, { ...options, mode: 'server' })
9195
}
9296

97+
/**
98+
* @deprecated use `useHeadSafe` instead.Advanced use cases should tree shake using import.meta.* if statements.
99+
*/
93100
export function useServerHeadSafe(input: UseHeadSafeInput = {}, options: UseHeadOptions = {}): ActiveHeadEntry<any> {
94101
return useHeadSafe(input, { ...options, mode: 'server' })
95102
}
96103

104+
/**
105+
* @deprecated use `useSeoMeta` instead.Advanced use cases should tree shake using import.meta.* if statements.
106+
*/
97107
export function useServerSeoMeta(input: UseSeoMetaInput = {}, options?: UseHeadOptions): ActiveHeadEntry<UseSeoMetaInput> {
98108
return useSeoMeta(input, { ...options, mode: 'server' })
99109
}

‎packages/vue/src/legacy.ts

+9
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,23 @@ export function useSeoMeta(input: UseSeoMetaInput, options?: UseHeadOptions): Ac
141141
}
142142
}
143143

144+
/**
145+
* @deprecated use `useHead` instead. Advanced use cases should tree shake using import.meta.* if statements.
146+
*/
144147
export function useServerHead<T extends MergeHead>(input: UseHeadInput<T>, options: UseHeadOptions = {}): ActiveHeadEntry<any> | void {
145148
return useHead(input, { ...options, mode: 'server' })
146149
}
147150

151+
/**
152+
* @deprecated use `useHeadSafe` instead. Advanced use cases should tree shake using import.meta.* if statements.
153+
*/
148154
export function useServerHeadSafe(input: UseHeadSafeInput, options: UseHeadOptions = {}): ActiveHeadEntry<any> | void {
149155
return useHeadSafe(input, { ...options, mode: 'server' })
150156
}
151157

158+
/**
159+
* @deprecated use `useSeoMeta` instead. Advanced use cases should tree shake using import.meta.* if statements.
160+
*/
152161
export function useServerSeoMeta(input: UseSeoMetaInput, options?: UseHeadOptions): ActiveHeadEntry<any> | void {
153162
return useSeoMeta(input, { ...options, mode: 'server' })
154163
}

0 commit comments

Comments
 (0)
Please sign in to comment.