Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

refactor(nuxt)!: move head option support into defineNuxtComponent #8901

Merged
merged 6 commits into from Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 18 additions & 2 deletions docs/content/3.api/3.utils/define-nuxt-component.md
Expand Up @@ -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
Expand All @@ -34,3 +34,19 @@ export default defineNuxtComponent({
})
</script>
```

## `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]
<script lang="ts">
export default defineNuxtComponent({
head(nuxtApp) {
return {
title: 'My site'
}
},
})
</script>
```
10 changes: 9 additions & 1 deletion packages/nuxt/src/app/composables/component.ts
Expand Up @@ -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<string, any> | Promise<Record<string, any>>, fn: (nuxtApp: NuxtApp) => Promise<Record<string, any>>) {
Expand All @@ -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
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/index.ts
Expand Up @@ -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
3 changes: 0 additions & 3 deletions packages/nuxt/src/head/module.ts
Expand Up @@ -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') })
}
Expand Down
6 changes: 0 additions & 6 deletions packages/nuxt/src/head/runtime/composables.ts
Expand Up @@ -12,9 +12,3 @@ import { useNuxtApp } from '#app'
export function useHead (meta: MaybeComputedRef<MetaObject>) {
useNuxtApp()._useHead(meta)
}

// TODO: remove useMeta support when Nuxt 3 is stable
/** @deprecated Please use new `useHead` composable instead */
export function useMeta (meta: MaybeComputedRef<MetaObject>) {
return useHead(meta)
}
24 changes: 0 additions & 24 deletions packages/nuxt/src/head/runtime/mixin-plugin.ts

This file was deleted.

3 changes: 1 addition & 2 deletions packages/nuxt/src/imports/presets.ts
Expand Up @@ -5,8 +5,7 @@ const commonPresets: InlinePreset[] = [
defineUnimportPreset({
from: '#head',
imports: [
'useHead',
'useMeta'
'useHead'
]
}),
// vue-demi (mocked)
Expand Down
1 change: 0 additions & 1 deletion test/basic.test.ts
Expand Up @@ -252,7 +252,6 @@ describe('head tags', () => {
expect(headHtml).toContain('<meta name="description" content="overriding with an inline useHead call">')
expect(headHtml).toMatch(/<html[^>]*class="html-attrs-test"/)
expect(headHtml).toMatch(/<body[^>]*class="body-attrs-test"/)
expect(headHtml).toContain('script>console.log("works with useMeta too")</script>')
expect(headHtml).toContain('<script src="https://a-body-appended-script.com" data-meta-body></script></body>')

const indexHtml = await $fetch('/')
Expand Down
1 change: 1 addition & 0 deletions test/bundle.test.ts
Expand Up @@ -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",
Expand Down
45 changes: 21 additions & 24 deletions test/fixtures/basic/pages/head.vue
@@ -1,35 +1,32 @@
<script setup>
const a = ref('')

useHead({
// title template function example
titleTemplate: title => `${title} - Title Template Fn Change`,
bodyAttrs: {
class: 'body-attrs-test'
},
script: [
{
src: 'https://a-body-appended-script.com',
body: true
}
],
meta: [{ name: 'description', content: 'first' }]
})
useHead({ meta: [{ charset: 'utf-16' }, { name: 'description', content: computed(() => `${a.value} with an inline useHead call`) }] })
useMeta({ script: [{ children: 'console.log("works with useMeta too")' }] })
a.value = 'overriding'
</script>

<script>
export default {
export default defineNuxtComponent({
head () {
return {
htmlAttrs: {
class: 'html-attrs-test'
}
}
},
setup () {
const a = ref('')
useHead({
// title template function example
titleTemplate: title => `${title} - Title Template Fn Change`,
bodyAttrs: {
class: 'body-attrs-test'
},
script: [
{
src: 'https://a-body-appended-script.com',
body: true
}
],
meta: [{ name: 'description', content: 'first' }]
})
useHead({ meta: [{ charset: 'utf-16' }, { name: 'description', content: computed(() => `${a.value} with an inline useHead call`) }] })
a.value = 'overriding'
}
}
})
</script>

<template>
Expand Down