unhead-vue-skilld
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseunjs/unhead @unhead/vue
@unhead/vueunjs/unhead @unhead/vue
@unhead/vueFull-stack <head> manager built for Vue.
Version: 2.1.10 (Mar 2026)
Deps: hookable@^6.0.1, unhead@2.1.10
Tags: next: 3.0.0-beta.9 (Feb 2026), beta: 3.0.0-beta.11 (Mar 2026), latest: 2.1.10 (Mar 2026)
References: Docs — API reference, guides
专为Vue构建的全栈<head>管理器。
版本: 2.1.10(2026年3月)
依赖: hookable@^6.0.1, unhead@2.1.10
标签: next: 3.0.0-beta.9(2026年2月), beta: 3.0.0-beta.11(2026年3月), latest: 2.1.10(2026年3月)
参考资料: 文档 — API参考、指南
API Changes
API变更
This section documents version-specific API changes — prioritize recent major/minor releases.
-
BREAKING:and
createHead()removed fromcreateServerHead()root in v2 — use subpath imports:@unhead/vuefromcreateHead()(SPA) or@unhead/vue/client(SSR);@unhead/vue/serverno longer exists sourcecreateServerHead() -
BREAKING: Implicit context removed in v2 —deleted;
setHeadInjectionHandler()called after anuseHead()in lifecycle hooks (e.g.await) throws because Vue context is lost; wrap async data fetching before callingonMountedsourceuseHead() -
BREAKING:and
vmidtag properties removed in v2 — usehidfor deduplication:keysourcescript: [{ key: 'my-key' }] -
BREAKING:tag property removed in v2 — use
childreninstead sourceinnerHTML -
BREAKING:tag property removed in v2 — use
body: trueinstead sourcetagPosition: 'bodyClose' -
BREAKING:no longer returns a Promise in v2 —
useScript()calls silently fail; use.then()instead source.onLoaded(() => ...) -
BREAKING:API no longer accessible directly on the instance in v2 — must use
useScript()explicitly:.proxynotscript.proxy.myFn(); code compiles but calls are lost at runtime sourcescript.myFn() -
BREAKING:option and
stub()hook removed fromscript:instance-fnin v2 — replace with customuseScript()logic sourceuse() -
BREAKING: Promise inputs inno longer auto-resolved in v2 — await the promise before passing, or opt in to
useHead()fromPromisePluginsource@unhead/vue/plugins -
BREAKING:and
TemplateParamsPluginno longer built-in in v2 — must opt in:AliasSortingPluginimported fromcreateHead({ plugins: [TemplateParamsPlugin, AliasSortingPlugin] })source@unhead/vue/plugins -
BREAKING: Capo.js tag sorting is now the default in v2 — breaks snapshot tests; opt out withsource
createHead({ disableCapoSorting: true }) -
DEPRECATED:,
useServerHead(),useServerHeadSafe()— useuseServerSeoMeta(),useHead(),useHeadSafe()withuseSeoMeta()conditionals orimport.meta.serveroption for tree-shaking{ mode: 'server' } -
NEW:,
<Head>,<Title>,<Meta>,<Link>template components — import from<Script>source@unhead/vue/components -
NEW:from
DeprecationsPlugin— re-enables removed@unhead/vue/plugins,vmid,hid,childrenproperties for gradual migration to v2 sourcebody
Also changed: deprecated — use instead · deprecated — use · Default SSR tags auto-inserted in v2 (, , ); disable with · CJS exports removed, ESM only · Vue 2 support removed · context lost after in Vue lifecycle hooks — fetch data first, then call
@unhead/schema@unhead/vue/typescreateHeadCorecreateUnheadcharsetviewporthtml lang="en"createHead({ disableDefaults: true })useHead()asyncuseHead()本部分记录对应版本的API变动,优先参考最新的主版本/次版本更新。
-
破坏性变更:v2版本中根导出移除了
@unhead/vue和createHead(),请使用子路径导入:从createServerHead()(SPA场景)或@unhead/vue/client(SSR场景)导入@unhead/vue/server;createHead()已被移除 来源createServerHead() -
破坏性变更:v2版本移除了隐式上下文,已删除;如果在生命周期钩子(如
setHeadInjectionHandler())的onMounted之后调用await会抛出错误,因为Vue上下文已丢失;请在调用useHead()之前完成异步数据获取 来源useHead() -
破坏性变更:v2版本移除了和
vmid标签属性,请使用hid实现去重:key来源script: [{ key: 'my-key' }] -
破坏性变更:v2版本移除了标签属性,请改用
children来源innerHTML -
破坏性变更:v2版本移除了标签属性,请改用
body: true来源tagPosition: 'bodyClose' -
破坏性变更:v2版本中不再返回Promise,
useScript()调用会静默失败,请改用.then()来源.onLoaded(() => ...) -
破坏性变更:v2版本中API不再可以直接在实例上访问,必须显式使用
useScript():调用方式为.proxy而非script.proxy.myFn();代码可正常编译但运行时调用会失效 来源script.myFn() -
破坏性变更:v2版本中移除了
useScript()选项和stub()钩子,请替换为自定义script:instance-fn逻辑 来源use() -
破坏性变更:v2版本中不再自动解析Promise类型的输入,请在传入前await该Promise,或者从
useHead()引入@unhead/vue/plugins主动开启该能力 来源PromisePlugin -
破坏性变更:v2版本不再内置和
TemplateParamsPlugin,需要主动引入使用:从AliasSortingPlugin导入后配置@unhead/vue/plugins来源createHead({ plugins: [TemplateParamsPlugin, AliasSortingPlugin] }) -
破坏性变更:v2版本默认开启Capo.js标签排序,会导致快照测试失败;可通过关闭该能力 来源
createHead({ disableCapoSorting: true }) -
已废弃:、
useServerHead()、useServerHeadSafe(),请改用useServerSeoMeta()、useHead()、useHeadSafe()配合useSeoMeta()条件判断,或者传入import.meta.server选项实现tree-shaking{ mode: 'server' } -
新增:、
<Head>、<Title>、<Meta>、<Link>模板组件,可从<Script>导入 来源@unhead/vue/components -
新增:导出的
@unhead/vue/plugins,可重新支持已移除的DeprecationsPlugin、vmid、hid、children属性,用于渐进式迁移到v2版本 来源body
其他变更: 已废弃,请改用 · 已废弃,请改用 · v2版本会自动插入默认SSR标签(、、);可通过关闭 · 移除了CJS导出,仅支持ESM · 移除了Vue 2支持 · Vue生命周期钩子中执行操作后会丢失上下文,请先获取数据再调用
@unhead/schema@unhead/vue/typescreateHeadCorecreateUnheadcharsetviewporthtml lang="en"createHead({ disableDefaults: true })asyncuseHead()useHead()Best Practices
最佳实践
-
Always usefrom
injectHead()instead of@unhead/vuefromgetActiveHead()in Vue components —unheadbinds to the Vue component context (visible ininjectHead()), whileonServerPrefetchreturns a shared cross-request instance that breaks in SSR. The maintainer confirmed this is the correct approach for Vue. sourcegetActiveHead() -
Avoid callinginside watchers — each call creates a new entry rather than updating the existing one, leading to duplicate entries. Instead, pass reactive refs or computed getters directly to a single
useHead()call at setup time so updates flow automatically. sourceuseHead() -
Whenmust be called after async operations (e.g. inside
useHead()), capture the head instance at setup time withonMountedand pass it asinjectHead()in the second argument — Vue's inject context is lost after{ head }. For most cases, prefer the reactive state pattern: defineawaitonce at setup with computed getters, and update auseHead()asynchronously. sourceref -
Useinstead of
useHeadSafe()whenever head input comes from user-provided or third-party sources — it enforces an attribute whitelist and strips script tags and event handlers, preventing XSS without requiring manual sanitization. sourceuseHead() -
Add theplugin from
UnheadVite()to your Vite config for Vue apps — it tree-shakes server-only composables from the client build and transforms@unhead/addons/vitecalls into rawuseSeoMeta()calls, saving ~3kb. Nuxt configures this automatically; standalone Vue apps must opt in. sourceuseHead() -
Passto
{ mode: 'server' }for static SEO metadata (Open Graph images, robots, schema.org) that doesn't need client-side reactivity — this strips the tags from the client bundle entirely. Similarly useuseHead()for analytics scripts to keep them out of SSR output. Caveat:{ mode: 'client' }must be included in both environments to avoid title flashing. sourcetitleTemplate -
Usefor non-critical scripts (analytics, chat widgets) instead of
tagPosition: 'bodyClose'— this prevents render-blocking and improves page load performance. Useheadaliases rather than raw numbers to preserve Capo.js-derived ordering weights that Unhead applies automatically. sourcetagPriority: 'critical' | 'high' | 'low' -
Useinstead of
textContentfor inline scripts and styles —innerHTMLescapes HTML characters, preventing injection. Only usetextContentwhen HTML entities are required, and sanitize the content yourself (e.g. with DOMPurify). For user-generated inline content, preferinnerHTMLwhich restricts scripts touseHeadSafe()only. sourcetype="application/json" -
Registerand define global
TemplateParamsPlugin(e.g.templateParams,siteName) once in your head instance setup rather than repeating them per page. These params work across all head tags — includingseparatorandog:titledescriptions — not justmeta. SettitleTemplateto a smart separator like%separatoror·; it auto-removes when adjacent to empty content. source— -
Useto automatically derive
InferSeoMetaPluginandog:titlefrom existingog:descriptionandtitletags, eliminating manual duplication. Configuredescriptionwith a transform function to strip the site name suffix from Open Graph titles (e.g. removingogTitlethat"| My Site"appends). sourcetitleTemplate
-
在Vue组件中始终使用导出的
@unhead/vue,而非injectHead()导出的unhead:getActiveHead()会绑定到Vue组件上下文(在injectHead()中可见),而onServerPrefetch返回的是跨请求共享的实例,会在SSR场景下出错。维护者已确认这是Vue场景下的正确用法。来源getActiveHead() -
避免在watcher中调用:每次调用都会创建新条目而非更新现有条目,会导致条目重复。正确做法是在setup阶段单次调用
useHead(),直接传入响应式ref或者计算属性,这样更新会自动生效。来源useHead() -
如果必须在异步操作后调用(例如在
useHead()内部),请在setup阶段通过onMounted提前获取head实例,然后在第二个参数中传入injectHead():Vue的inject上下文会在{ head }后丢失。大多数场景下更推荐使用响应式状态模式:在setup阶段定义await并传入计算属性,异步更新对应的ref即可。来源useHead() -
当head的输入内容来自用户提供或第三方来源时,请使用而非
useHeadSafe():它会强制执行属性白名单,剥离script标签和事件处理器,无需手动清理即可防范XSS。来源useHead() -
Vue应用请在Vite配置中添加导出的
@unhead/addons/vite插件:它会从客户端构建产物中tree-shake掉仅服务端使用的组合式API,并且将UnheadVite()调用转换为原生的useSeoMeta()调用,可减少约3kb体积。Nuxt会自动配置该插件,独立Vue应用需要主动引入。来源useHead() -
对于不需要客户端响应性的静态SEO元数据(Open Graph图片、robots、schema.org),请给传入
useHead():这会将对应标签从客户端包中完全剔除。同理,对于分析脚本可以传入{ mode: 'server' },避免它们出现在SSR输出中。注意:{ mode: 'client' }需要在两个环境中都配置,避免标题闪烁。来源titleTemplate -
非关键脚本(分析、聊天组件)请使用而非放在head中:这可以避免阻塞渲染,提升页面加载性能。请使用
tagPosition: 'bodyClose'别名而非原始数字优先级,以保留Unhead自动应用的Capo.js排序权重。来源tagPriority: 'critical' | 'high' | 'low' -
内联脚本和样式请使用而非
textContent:innerHTML会转义HTML字符,防范注入攻击。仅当需要HTML实体时才使用textContent,并且请自行清理内容(例如使用DOMPurify)。对于用户生成的内联内容,更推荐使用innerHTML,它仅允许useHeadSafe()类型的脚本。来源type="application/json" -
请在head实例初始化阶段注册并一次性定义全局
TemplateParamsPlugin(例如templateParams、siteName),不要在每个页面重复定义。这些参数对所有head标签都生效——包括separator和meta描述,不只是og:title。可以将titleTemplate设置为%separator或·这类智能分隔符,相邻内容为空时会自动移除。来源— -
使用可以自动从已有的
InferSeoMetaPlugin和title标签生成description和og:title,无需手动重复配置。可以给og:description配置转换函数,去除Open Graph标题中的站点名称后缀(例如移除ogTitle追加的titleTemplate)。来源"| My Site"