Skip to content

Commit

Permalink
perf(head): drop @vueuse/head dependency (#19519)
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw committed Mar 8, 2023
1 parent df3ae8c commit 8732720
Show file tree
Hide file tree
Showing 16 changed files with 130 additions and 73 deletions.
12 changes: 7 additions & 5 deletions docs/1.getting-started/5.seo-meta.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ export default defineNuxtConfig({

## Composable: `useHead`

The `useHead` composable function allows you to manage your head tags in a programmatic and reactive way, powered by [@vueuse/head](https://github.com/vueuse/head).
The `useHead` composable function allows you to manage your head tags in a programmatic and reactive way,
powered by [Unhead](https://unhead.harlanzw.com/).

As with all composables, it can only be used with a components `setup` and lifecycle hooks.

Expand All @@ -62,7 +63,7 @@ useHead({
bodyAttrs: {
class: 'test'
},
script: [ { children: 'console.log(\'Hello world\')' } ]
script: [ { innerHTML: 'console.log(\'Hello world\')' } ]
})
</script>
```
Expand Down Expand Up @@ -153,6 +154,7 @@ The below is the non-reactive types used for `useHead`, `app.head` and component
interface MetaObject {
title?: string
titleTemplate?: string | ((title?: string) => string)
templateParams?: Record<string, string | Record<string, string>>
base?: Base
link?: Link[]
meta?: Meta[]
Expand All @@ -164,7 +166,7 @@ interface MetaObject {
}
```

See [zhead](https://github.com/harlan-zw/zhead/tree/main/packages/schema/src) for more detailed types.
See [@unhead/schema](https://github.com/unjs/unhead/blob/main/packages/schema/src/schema.ts) for more detailed types.

## Features

Expand Down Expand Up @@ -228,7 +230,7 @@ Now, if you set the title to `My Page` with `useHead` on another page of your si

### Body Tags

You can use the `body: true` option on the `link` and `script` meta tags to append them to the end of the `<body>` tag.
You can use the `tagPosition: 'bodyClose'` option on applicable tags to append them to the end of the `<body>` tag.

For example:

Expand All @@ -238,7 +240,7 @@ useHead({
script: [
{
src: 'https://third-party-script.com',
body: true
tagPosition: 'bodyClose' // valid options are: 'head' | 'bodyClose' | 'bodyOpen'
}
]
})
Expand Down
8 changes: 4 additions & 4 deletions docs/3.api/1.composables/use-head.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ description: useHead customizes the head properties of individual pages of your

# `useHead`

Nuxt provides the `useHead` composable to add and customize the head properties of individual pages of your Nuxt app.

`useHead` is powered by [@vueuse/head](https://github.com/vueuse/head), you can find more in-depth documentation [here](https://unhead.harlanzw.com/)
The `useHead` composable function allows you to manage your head tags in a programmatic and reactive way, powered by [Unhead](https://unhead.harlanzw.com/).

::ReadMore{link="/docs/getting-started/seo-meta"}
::
Expand All @@ -17,7 +15,7 @@ Nuxt provides the `useHead` composable to add and customize the head properties
useHead(meta: MaybeComputedRef<MetaObject>): void
```

Below are the non-reactive types for `useHead`. See [zhead](https://github.com/harlan-zw/zhead/tree/main/packages/schema/src) for more detailed types.
Below are the non-reactive types for `useHead`.

```ts
interface MetaObject {
Expand All @@ -34,6 +32,8 @@ interface MetaObject {
}
```

See [@unhead/schema](https://github.com/unjs/unhead/blob/main/packages/schema/src/schema.ts) for more detailed types.

::alert{type=info}
The properties of `useHead` can be dynamic, accepting `ref`, `computed` and `reactive` properties. `meta` parameter can also accept a function returning an object to make the entire object reactive.
::
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ export default defineBuildConfig({
'nuxt/schema',
'@vue/reactivity',
'@vue/shared',
'@vueuse/head'
'@unhead/vue'
]
})
5 changes: 2 additions & 3 deletions packages/nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@
"@nuxt/telemetry": "^2.1.10",
"@nuxt/ui-templates": "^1.1.1",
"@nuxt/vite-builder": "3.2.3",
"@unhead/ssr": "^1.1.16",
"@unhead/ssr": "^1.1.20",
"@unhead/vue": "^1.1.20",
"@vue/reactivity": "^3.2.47",
"@vue/shared": "^3.2.47",
"@vueuse/head": "^1.1.15",
"chokidar": "^3.5.3",
"cookie-es": "^0.5.0",
"defu": "^6.1.2",
Expand All @@ -82,7 +82,6 @@
"ufo": "^1.1.1",
"unctx": "^2.1.2",
"unenv": "^1.2.1",
"unhead": "^1.1.16",
"unimport": "^3.0.2",
"unplugin": "^1.1.0",
"untyped": "^1.2.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/core/nitro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import escapeRE from 'escape-string-regexp'
import { defu } from 'defu'
import fsExtra from 'fs-extra'
import { dynamicEventHandler } from 'h3'
import { createHeadCore } from 'unhead'
import { createHeadCore } from '@unhead/vue'
import { renderSSRHead } from '@unhead/ssr'
import { distDir } from '../dirs'
import { ImportProtectionPlugin } from './plugins/import-protection'
Expand Down
16 changes: 11 additions & 5 deletions packages/nuxt/src/head/module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { resolve } from 'pathe'
import { addComponent, addPlugin, defineNuxtModule } from '@nuxt/kit'
import { addComponent, addPlugin, defineNuxtModule, tryResolveModule } from '@nuxt/kit'
import { distDir } from '../dirs'

const components = ['NoScript', 'Link', 'Base', 'Title', 'Meta', 'Style', 'Head', 'Html', 'Body']
Expand All @@ -11,8 +11,8 @@ export default defineNuxtModule({
setup (options, nuxt) {
const runtimeDir = nuxt.options.alias['#head'] || resolve(distDir, 'head/runtime')

// Transpile @nuxt/meta and @vueuse/head
nuxt.options.build.transpile.push('@vueuse/head')
// Transpile @unhead/vue
nuxt.options.build.transpile.push('@unhead/vue')

// Add #head alias
nuxt.options.alias['#head'] = runtimeDir
Expand All @@ -30,8 +30,14 @@ export default defineNuxtModule({
kebabName: componentName
})
}
// Opt-out feature allowing dependencies using @vueuse/head to work
if (nuxt.options.experimental.polyfillVueUseHead) {
// backwards compatibility
nuxt.options.alias['@vueuse/head'] = tryResolveModule('@unhead/vue') || '@unhead/vue'
addPlugin({ src: resolve(runtimeDir, 'lib/vueuse-head-polyfill.plugin') })
}

// Add library specific plugin
addPlugin({ src: resolve(runtimeDir, 'lib/vueuse-head.plugin') })
// Add library-specific plugin
addPlugin({ src: resolve(runtimeDir, 'lib/unhead.plugin') })
}
})
4 changes: 2 additions & 2 deletions packages/nuxt/src/head/runtime/composables.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { HeadEntryOptions, UseHeadInput, ActiveHeadEntry } from '@vueuse/head'
import { useSeoMeta as _useSeoMeta } from '@vueuse/head'
import type { HeadEntryOptions, UseHeadInput, ActiveHeadEntry } from '@unhead/vue'
import { useSeoMeta as _useSeoMeta } from '@unhead/vue'
import type { HeadAugmentations } from 'nuxt/schema'
import { useNuxtApp } from '#app/nuxt'

Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/head/runtime/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { UseHeadInput } from '@vueuse/head'
import type { UseHeadInput } from '@unhead/vue'
import type { HeadAugmentations } from 'nuxt/schema'

export * from './composables'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createHead, useHead } from '@vueuse/head'
import { createHead, useHead } from '@unhead/vue'
import { renderSSRHead } from '@unhead/ssr'
import { defineNuxtPlugin } from '#app/nuxt'
// @ts-expect-error untyped
Expand All @@ -16,25 +16,25 @@ export default defineNuxtPlugin((nuxtApp) => {
const unpauseDom = () => {
pauseDOMUpdates = false
// triggers dom update
head.internalHooks.callHook('entries:updated', head.unhead)
head.hooks.callHook('entries:updated', head)
}
head.internalHooks.hook('dom:beforeRender', (context) => { context.shouldRender = !pauseDOMUpdates })
head.hooks.hook('dom:beforeRender', (context) => { context.shouldRender = !pauseDOMUpdates })
nuxtApp.hooks.hook('page:start', () => { pauseDOMUpdates = true })
// wait for new page before unpausing dom updates (triggered after suspense resolved)
nuxtApp.hooks.hook('page:finish', unpauseDom)
nuxtApp.hooks.hook('app:mounted', unpauseDom)
}

// useHead does not depend on a vue component context, we keep it on the nuxtApp for backwards compatibility
// support backwards compatibility, remove at some point
nuxtApp._useHead = useHead

if (process.server) {
nuxtApp.ssrContext!.renderMeta = async () => {
const meta = await renderSSRHead(head.unhead)
const meta = await renderSSRHead(head)
return {
...meta,
bodyScriptsPrepend: meta.bodyTagsOpen,
// resolves naming difference with NuxtMeta and @vueuse/head
// resolves naming difference with NuxtMeta and Unhead
bodyScripts: meta.bodyTags
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @ts-expect-error ts failing with type
import { polyfillAsVueUseHead } from '@unhead/vue/polyfill'
import { defineNuxtPlugin } from '#app/nuxt'

export default defineNuxtPlugin((nuxtApp) => {
// avoid breaking ecosystem dependencies using low-level @vueuse/head APIs
polyfillAsVueUseHead(nuxtApp.vueApp._context.provides.usehead)
})
10 changes: 9 additions & 1 deletion packages/schema/src/config/experimental.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ export default defineUntypedSchema({
*
* @see https://github.com/nuxt/nuxt/issues/15592
*/
configSchema: true
configSchema: true,

/**
* Whether or not to add a compatibility layer for modules, plugins or user code relying on the old
* `@vueuse/head` API.
*
* This can be disabled for most Nuxt sites to reduce the client-side bundle by ~0.5kb.
*/
polyfillVueUseHead: true
}
})
72 changes: 33 additions & 39 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8732720

Please sign in to comment.