Migration
Applies to @unhead/vue 3.4.1. Sources: dist type definitions, https://unhead.unjs.io/docs/vue/head/guides/get-started/migration, https://unhead.unjs.io/docs/migration-guide/v3, https://unhead.unjs.io/docs/releases/v3.
v3 status of v2 deprecations
The v3 docs describe several exports as removed. In the shipped 3.4.1 types they are still present but deprecated; plan for removal in v4:
| Export | 3.4.1 status | Evidence | Replace with |
|---|---|---|---|
useServerHead, useServerHeadSafe, useServerSeoMeta |
deprecated aliases of the plain composables | dist/index.d.ts:26-30 | useHead / useHeadSafe / useSeoMeta + if (import.meta.server) |
@unhead/vue/legacy createHead, createServerHead, legacyPlugins |
deprecated, removal in v4 | dist/legacy.d.ts:14-30 | @unhead/vue/client / @unhead/vue/server |
resolveUnrefHeadInput |
deprecated | dist/utils.d.ts:9 | resolveTags(head) from unhead/utils |
unheadVuePlugin (@unhead/vue/stream/vite) |
deprecated | dist/stream/vite.d.ts:8 | Unhead({ streaming: true }).vite() from @unhead/vue/bundler |
MergeHead type |
deprecated | dist/types.d.ts:66 | VueHeadClient generics |
Removed in v3 (compile errors if used)
DeprecationsPlugin: no auto-conversion ofchildren/hid/vmid/body: true; rename props directly (innerHTML,key,key,tagPosition: 'bodyClose').setHeadInjectionHandler: head injection is automatic via Vue provide/inject.createHeadCore(bothunheadand@unhead/vue): usecreateUnhead()orcreateHead()from/client///server.{ mode: 'server' }entry option: silently ignored; useimport.meta.serverconditionals.- Hooks
init,dom:renderTag,dom:rendered(use theonRenderedoption onuseHead());dom:beforeRenderand allssr:*hooks are synchronous;renderDOMHeadandrenderSSRHeadno longer return Promises. head.headEntries(): use[...head.entries.values()].- Types
Head,MetaFlatInput,RuntimeMode,ResolvedHead,ResolvedMetaFlat: useHeadTag,MetaFlat, etc. @unhead/addonspackage: renamed@unhead/bundler; default export replaced by namedUnhead.
Strict tag types (v3)
Link and Script inputs are discriminated unions:
- Font preloads require
crossorigin:{ rel: 'preload', as: 'font', href: '/f.woff2', crossorigin: 'anonymous' }. - Inline scripts need
textContent/innerHTMLand cannot carrysrc/async/defer. - Meta with
name,property, orhttp-equivrequirescontent; usecontent: nullto remove the tag. - Non-literal
rel/typestrings break narrowing: wrap withdefineLink()/defineScript()or useas const.
v2 -> v3 quick diffs
- import { createHead } from '@unhead/vue/legacy'
+ import { createHead } from '@unhead/vue/client' // SPA
+ import { createHead } from '@unhead/vue/server' // SSR
- import { useServerHead } from '@unhead/vue'
+ if (import.meta.server) { useHead({ title: 'Server Only' }) }
- const tags = await renderSSRHead(head)
+ const tags = renderSSRHead(head)
- import type { Head, MetaFlatInput } from '@unhead/vue'
+ import type { HeadTag, MetaFlat } from '@unhead/vue'
- import unhead from '@unhead/addons/vite'
+ import { Unhead } from '@unhead/vue/vite' // or '@unhead/vue/bundler'v1 -> v2 (still relevant)
createHead/createServerHeadmoved off the package root to/clientand/serversubpaths.vmid,hid,children,body: trueremoved in favor ofkey,innerHTML,tagPosition.useScript()no longer thenable; useonLoaded(). API access via.proxyonly.stub()and thescript:instance-fnhook removed.- Promise inputs not resolved by default: await first, or register
PromisePluginfrom@unhead/vue/plugins. TemplateParamsPluginandAliasSortingPluginare opt-in atcreateHead({ plugins: [...] }).- Capo.js tag sorting is default (
disableCapoSorting: trueto opt out); default SSR tags are auto-inserted (disableDefaults: trueto opt out). - Vue 2 support and CJS exports removed.