diff --git a/docs/content/3.api/3.utils/define-nuxt-component.md b/docs/content/3.api/3.utils/define-nuxt-component.md
index 49c0960b9b6..d245c5b4bb6 100644
--- a/docs/content/3.api/3.utils/define-nuxt-component.md
+++ b/docs/content/3.api/3.utils/define-nuxt-component.md
@@ -5,10 +5,10 @@ description: defineNuxtComponent() is a helper function for defining type safe c
# `defineNuxtComponent`
-`defineNuxtComponent()` is a helper function for defining type safe Vue components using options API similar to [defineComponent()](https://vuejs.org/api/general.html#definecomponent). `defineNuxtComponent()` wrapper also adds support for `asyncData` component option.
+`defineNuxtComponent()` is a helper function for defining type safe Vue components using options API similar to [defineComponent()](https://vuejs.org/api/general.html#definecomponent). `defineNuxtComponent()` wrapper also adds support for `asyncData` and `head` component options.
::alert{type=warning}
-Options API support for `asyncData` may well change before the stable release of Nuxt 3.
+Options API support for `asyncData` and `head` may well change before the stable release of Nuxt 3.
::
::Alert
@@ -34,3 +34,19 @@ export default defineNuxtComponent({
})
```
+
+## `head()`
+
+If you choose not to use `setup()` in your app, you can use the `head()` method within your component definition:
+
+```vue [pages/index.vue]
+
+```
diff --git a/packages/nuxt/src/app/composables/component.ts b/packages/nuxt/src/app/composables/component.ts
index bceff5e2322..bdd8b61ea1b 100644
--- a/packages/nuxt/src/app/composables/component.ts
+++ b/packages/nuxt/src/app/composables/component.ts
@@ -4,6 +4,9 @@ import { NuxtApp, useNuxtApp } from '../nuxt'
import { useAsyncData } from './asyncData'
import { useRoute } from './router'
+// eslint-disable-next-line import/no-restricted-paths
+import { useHead } from '#head'
+
export const NuxtComponentIndicator = '__nuxt_component'
async function runLegacyAsyncData (res: Record | Promise>, fn: (nuxtApp: NuxtApp) => Promise>) {
@@ -25,7 +28,7 @@ export const defineNuxtComponent: typeof defineComponent =
const { setup } = options
// Avoid wrapping if no options api is used
- if (!setup && !options.asyncData) {
+ if (!setup && !options.asyncData && !options.head) {
return {
[NuxtComponentIndicator]: true,
...options
@@ -43,6 +46,11 @@ export const defineNuxtComponent: typeof defineComponent =
promises.push(runLegacyAsyncData(res, options.asyncData))
}
+ if (options.head) {
+ const nuxtApp = useNuxtApp()
+ useHead(typeof options.head === 'function' ? () => options.head(nuxtApp) : options.head)
+ }
+
return Promise.resolve(res)
.then(() => Promise.all(promises))
.then(() => res)
diff --git a/packages/nuxt/src/app/index.ts b/packages/nuxt/src/app/index.ts
index 9920eb30e3b..37bd3f93a45 100644
--- a/packages/nuxt/src/app/index.ts
+++ b/packages/nuxt/src/app/index.ts
@@ -10,7 +10,7 @@ export type { PageMeta } from '../pages/runtime'
// eslint-disable-next-line import/no-restricted-paths
export type { MetaObject } from '../head/runtime'
// eslint-disable-next-line import/no-restricted-paths
-export { useHead, useMeta } from '#head'
+export { useHead } from '#head'
export const isVue2 = false
export const isVue3 = true
diff --git a/packages/nuxt/src/head/module.ts b/packages/nuxt/src/head/module.ts
index 263ced169b3..b6993629be7 100644
--- a/packages/nuxt/src/head/module.ts
+++ b/packages/nuxt/src/head/module.ts
@@ -29,9 +29,6 @@ export default defineNuxtModule({
})
}
- // Add mixin plugin
- addPlugin({ src: resolve(runtimeDir, 'mixin-plugin') })
-
// Add library specific plugin
addPlugin({ src: resolve(runtimeDir, 'lib/vueuse-head.plugin') })
}
diff --git a/packages/nuxt/src/head/runtime/composables.ts b/packages/nuxt/src/head/runtime/composables.ts
index d404b4f2f09..9516ede023a 100644
--- a/packages/nuxt/src/head/runtime/composables.ts
+++ b/packages/nuxt/src/head/runtime/composables.ts
@@ -12,9 +12,3 @@ import { useNuxtApp } from '#app'
export function useHead (meta: MaybeComputedRef) {
useNuxtApp()._useHead(meta)
}
-
-// TODO: remove useMeta support when Nuxt 3 is stable
-/** @deprecated Please use new `useHead` composable instead */
-export function useMeta (meta: MaybeComputedRef) {
- return useHead(meta)
-}
diff --git a/packages/nuxt/src/head/runtime/mixin-plugin.ts b/packages/nuxt/src/head/runtime/mixin-plugin.ts
deleted file mode 100644
index 906211527be..00000000000
--- a/packages/nuxt/src/head/runtime/mixin-plugin.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { getCurrentInstance } from 'vue'
-import { useHead } from './composables'
-import { defineNuxtPlugin, useNuxtApp } from '#app'
-
-const metaMixin = {
- created () {
- const instance = getCurrentInstance()
- if (!instance) { return }
-
- const options = instance.type
- if (!options || !('head' in options)) { return }
-
- const nuxtApp = useNuxtApp()
- const source = typeof options.head === 'function'
- ? () => options.head(nuxtApp)
- : options.head
-
- useHead(source)
- }
-}
-
-export default defineNuxtPlugin((nuxtApp) => {
- nuxtApp.vueApp.mixin(metaMixin)
-})
diff --git a/packages/nuxt/src/imports/presets.ts b/packages/nuxt/src/imports/presets.ts
index 5c29c86eeed..0cdfff6d245 100644
--- a/packages/nuxt/src/imports/presets.ts
+++ b/packages/nuxt/src/imports/presets.ts
@@ -5,8 +5,7 @@ const commonPresets: InlinePreset[] = [
defineUnimportPreset({
from: '#head',
imports: [
- 'useHead',
- 'useMeta'
+ 'useHead'
]
}),
// vue-demi (mocked)
diff --git a/test/basic.test.ts b/test/basic.test.ts
index b1a9105930e..f5e50add652 100644
--- a/test/basic.test.ts
+++ b/test/basic.test.ts
@@ -253,7 +253,6 @@ describe('head tags', () => {
expect(headHtml).toContain('')
expect(headHtml).toMatch(/]*class="html-attrs-test"/)
expect(headHtml).toMatch(/]*class="body-attrs-test"/)
- expect(headHtml).toContain('script>console.log("works with useMeta too")')
expect(headHtml).toContain('')
const indexHtml = await $fetch('/')
diff --git a/test/bundle.test.ts b/test/bundle.test.ts
index 1ec71193e98..22e4ea5d22b 100644
--- a/test/bundle.test.ts
+++ b/test/bundle.test.ts
@@ -29,6 +29,7 @@ describe.skipIf(isWindows)('minimal nuxt application', () => {
expect(stats.client.totalBytes).toBeLessThan(110000)
expect(stats.client.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
[
+ "_nuxt/composables.js",
"_nuxt/entry.js",
"_nuxt/error-404.js",
"_nuxt/error-500.js",
diff --git a/test/fixtures/basic/pages/head.vue b/test/fixtures/basic/pages/head.vue
index ee3328b8a3f..58ce42d2668 100644
--- a/test/fixtures/basic/pages/head.vue
+++ b/test/fixtures/basic/pages/head.vue
@@ -1,35 +1,32 @@
-
-