Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(head): drop @vueuse/head dependency #19519

Merged
merged 13 commits into from
Mar 8, 2023
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
danielroe marked this conversation as resolved.
Show resolved Hide resolved

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.

Loading