๐ŸŒ AIๆœ็ดข & ไปฃ็† ไธป้กต
Skip to content

Conversation

@harlan-zw
Copy link
Collaborator

@harlan-zw harlan-zw commented Dec 26, 2025

๐Ÿ”— Linked issue

โ“ Type of change

  • ๐Ÿ“– Documentation (updates to the documentation or readme)
  • ๐Ÿž Bug fix (a non-breaking change that fixes an issue)
  • ๐Ÿ‘Œ Enhancement (improving an existing functionality)
  • โœจ New feature (a non-breaking change that adds functionality)
  • ๐Ÿงน Chore (updates to the build process or auxiliary tools and libraries)
  • โš ๏ธ Breaking change (fix or feature that would cause existing functionality to change)

๐Ÿ“š Description

Drops all deprecated items from Unhead v2.

1. Legacy Property Names

Impact: High - Many existing codebases use these legacy property names.

The DeprecationsPlugin that automatically converted legacy property names has been removed. You must update your head entries to use the current property names.

children โ†’ innerHTML

head.push({
  script: [{
-   children: 'console.log("hello")',
+   innerHTML: 'console.log("hello")',
  }]
})

hid / vmid โ†’ key

head.push({
  meta: [{
-   hid: 'description',
+   key: 'description',
    name: 'description',
    content: 'My description'
  }]
})
head.push({
  meta: [{
-   vmid: 'og:title',
+   key: 'og:title',
    property: 'og:title',
    content: 'My Title'
  }]
})

body: true โ†’ tagPosition: 'bodyClose'

head.push({
  script: [{
    src: '/script.js',
-   body: true,
+   tagPosition: 'bodyClose',
  }]
})

Quick Reference

Old Property New Property
children innerHTML
hid key
vmid key
body: true tagPosition: 'bodyClose'

2. Schema.org Plugin

Impact: High - Anyone using @unhead/schema-org will need to update.

The PluginSchemaOrg and SchemaOrgUnheadPlugin exports have been removed. Use UnheadSchemaOrg instead.

- import { PluginSchemaOrg } from '@unhead/schema-org'
+ import { UnheadSchemaOrg } from '@unhead/schema-org'

const head = createHead({
  plugins: [
-   PluginSchemaOrg()
+   UnheadSchemaOrg()
  ]
})
- import { SchemaOrgUnheadPlugin } from '@unhead/schema-org'
+ import { UnheadSchemaOrg } from '@unhead/schema-org'

const head = createHead({
  plugins: [
-   SchemaOrgUnheadPlugin()
+   UnheadSchemaOrg()
  ]
})

For Vue users:

- import { PluginSchemaOrg } from '@unhead/schema-org/vue'
+ import { UnheadSchemaOrg } from '@unhead/schema-org/vue'

3. Server Composables

Impact: Medium-High - Common in SSR applications.

The useServerHead, useServerHeadSafe, and useServerSeoMeta composables have been removed. Use the standard composables instead.

useServerHead โ†’ useHead

- import { useServerHead } from 'unhead'
+ import { useHead } from 'unhead'

- useServerHead({ title: 'My Page' })
+ useHead({ title: 'My Page' })

useServerHeadSafe โ†’ useHeadSafe

- import { useServerHeadSafe } from 'unhead'
+ import { useHeadSafe } from 'unhead'

- useServerHeadSafe({ title: userInput })
+ useHeadSafe({ title: userInput })

useServerSeoMeta โ†’ useSeoMeta

- import { useServerSeoMeta } from 'unhead'
+ import { useSeoMeta } from 'unhead'

- useServerSeoMeta({ description: 'My description' })
+ useSeoMeta({ description: 'My description' })

Note: If you need server-only head management, use conditional logic or framework-specific SSR detection instead of mode-based composables.


4. Vue Legacy Exports

Impact: Medium - Affects Vue users on older setups.

/legacy Export Path Removed

The /legacy export path has been removed from @unhead/vue.

- import { createHead } from '@unhead/vue/legacy'
+ import { createHead } from '@unhead/vue/client'
// or for SSR
+ import { createHead } from '@unhead/vue/server'

createHeadCore Removed

- import { createHeadCore } from '@unhead/vue'
+ import { createHead } from '@unhead/vue/server'
// or for client
+ import { createHead } from '@unhead/vue/client'

5. Core API Changes

Impact: Medium - Affects custom integrations and advanced usage.

createHeadCore โ†’ createUnhead

- import { createHeadCore } from 'unhead'
+ import { createUnhead } from 'unhead'

- const head = createHeadCore()
+ const head = createUnhead()

headEntries() โ†’ entries Map

The headEntries() method has been removed. Access entries directly via the entries Map.

- const entries = head.headEntries()
+ const entries = [...head.entries.values()]

mode Option Removed

The mode option on head entries has been removed. Runtime mode detection is no longer supported.

head.push({
  title: 'My Page',
- }, { mode: 'server' })
+ })

If you need server-only or client-only head management, use the appropriate createHead function:

// Client-side
import { createHead } from 'unhead/client'

// Server-side
import { createHead } from 'unhead/server'

6. Schema.org Config Options

Impact: Low-Medium - Affects users with custom Schema.org configuration.

The following Schema.org config options have been removed:

Removed Option Replacement
canonicalHost host
canonicalUrl path + host
position Use tagPosition on individual schema entries
defaultLanguage Use inLanguage on schema nodes
defaultCurrency Use priceCurrency on schema nodes
UnheadSchemaOrg({
- canonicalHost: 'https://example.com',
- canonicalUrl: 'https://example.com/page',
+ host: 'https://example.com',
+ path: '/page',
})

7. Server Utilities

Impact: Low - Only affects users parsing HTML for head extraction.

extractUnheadInputFromHtml โ†’ parseHtmlForUnheadExtraction

The function has been moved from unhead/server to unhead/parser.

- import { extractUnheadInputFromHtml } from 'unhead/server'
+ import { parseHtmlForUnheadExtraction } from 'unhead/parser'

- const { input } = extractUnheadInputFromHtml(html)
+ const { input } = parseHtmlForUnheadExtraction(html)

8. Type Changes

Impact: Low - Only affects TypeScript users with explicit type imports.

Removed Type Aliases

Removed Type Replacement
Head HeadTag or specific tag types
ResolvedHead ResolvedHeadTag
MergeHead Use generics directly
MetaFlatInput MetaFlat
ResolvedMetaFlat MetaFlat
RuntimeMode Removed (no replacement needed)
- import type { Head, MetaFlatInput, RuntimeMode } from 'unhead'
+ import type { HeadTag, MetaFlat } from 'unhead'

9. Hooks

Impact: Low - Only affects users with custom hook implementations.

init Hook Removed

The init hook has been removed from HeadHooks.

- head.hooks.hook('init', (ctx) => {
-   // Initialize something
- })

dom:renderTag Hook Removed

The dom:renderTag hook has been removed. This hook was called for each tag during DOM rendering.

- head.hooks.hook('dom:renderTag', (ctx, document, track) => {
-   // Custom tag rendering logic
- })

dom:rendered Hook Removed

The dom:rendered hook has been removed. DOM rendering is now synchronous.

- head.hooks.hook('dom:rendered', ({ renders }) => {
-   // Post-render logic
- })

If you need to run logic after DOM rendering, call renderDOMHead directly and add your logic after:

import { renderDOMHead } from 'unhead/client'

renderDOMHead(head)
// Your post-render logic here

dom:beforeRender is Now Synchronous

The dom:beforeRender hook no longer supports async handlers.

head.hooks.hook('dom:beforeRender', (ctx) => {
-   await someAsyncOperation()
    ctx.shouldRender = true
})

renderDOMHead is Now Synchronous

The renderDOMHead function no longer returns a Promise.

- await renderDOMHead(head, { document })
+ renderDOMHead(head, { document })

10. Other Removed APIs

Impact: Low - Internal utilities rarely used directly.

resolveScriptKey

The resolveScriptKey function is no longer exported. This was an internal utility.

resolveUnrefHeadInput (Vue)

- import { resolveUnrefHeadInput } from '@unhead/vue'

Reactive head input resolution now happens automatically within the head manager.

setHeadInjectionHandler (Vue)

- import { setHeadInjectionHandler } from '@unhead/vue'
- setHeadInjectionHandler(() => myHead)

Head injection is now handled automatically.

DeprecationsPlugin

- import { DeprecationsPlugin } from 'unhead/plugins'

Instead of using this plugin, update your code to use the current property names (see Section 1).


Quick Reference: Import Changes

// Legacy properties - update property names directly, no plugin needed
- import { DeprecationsPlugin } from 'unhead/plugins'

// Schema.org
- import { PluginSchemaOrg, SchemaOrgUnheadPlugin } from '@unhead/schema-org'
+ import { UnheadSchemaOrg } from '@unhead/schema-org'

// Server composables
- import { useServerHead, useServerHeadSafe, useServerSeoMeta } from 'unhead'
+ import { useHead, useHeadSafe, useSeoMeta } from 'unhead'

// Core
- import { createHeadCore } from 'unhead'
+ import { createUnhead } from 'unhead'

// Server utilities
- import { extractUnheadInputFromHtml } from 'unhead/server'
+ import { parseHtmlForUnheadExtraction } from 'unhead/parser'

// Vue
- import { createHeadCore, resolveUnrefHeadInput, setHeadInjectionHandler } from '@unhead/vue'
- import { ... } from '@unhead/vue/legacy'
+ import { createHead } from '@unhead/vue/client'
+ import { createHead } from '@unhead/vue/server'

@harlan-zw harlan-zw merged commit 229d395 into v3 Dec 26, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants