Skip to content

Conversation

@harlan-zw
Copy link
Collaborator

@harlan-zw harlan-zw commented Jan 4, 2026

πŸ”— 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

Refactors rendering to be pluggable via factory functions. Enables better tree-shaking/bundling when using streaming SSR by allowing renderer to be passed in rather than imported internally.

Changes

  • createUnhead(renderer, options) - renderer is now first argument
  • head.render() - new unified method replaces direct render calls
  • createDomRenderer(options) / createServerRenderer(options) - new factory functions
  • Client head exposes dirty and invalidate() directly on instance
  • Entry dirty-tracking via _dirty flag replaces _normalizeQueue Set

Breaking Changes

createUnhead signature changed

// Before
const head = createUnhead({ plugins: [...] })

// After
const head = createUnhead(renderer, { plugins: [...] })

domOptions.render β†’ render

// Before
createHead({
  domOptions: {
    render: createDebouncedFn(() => renderDOMHead(head), fn => setTimeout(fn, 0)),
  },
})

// After
const domRenderer = createDomRenderer()
createHead({
  render: createDebouncedFn(() => domRenderer(head), fn => setTimeout(fn, 0)),
})

Use head.render() instead of standalone functions

// Before
import { renderSSRHead } from 'unhead/server'
const { headTags, bodyTags } = renderSSRHead(head)

// After
const { headTags, bodyTags } = head.render()
// Before
import { renderDOMHead } from 'unhead/client'
renderDOMHead(head)

// After
head.render()

invalidate() moved to client head only

// Before (worked on any head)
head.invalidate()

// After (client head only)
head.invalidate() // only available on client createHead()

Note: renderSSRHead and renderDOMHead still exported but deprecated.

@harlan-zw harlan-zw changed the title fix!: pluggable render functions fix!: pluggable render() function Jan 4, 2026
@harlan-zw harlan-zw merged commit baaa773 into v3 Jan 4, 2026
1 check passed
@harlan-zw harlan-zw mentioned this pull request Jan 4, 2026
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