mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 13:45:18 +00:00
refactor(nuxt3,bridge)!: rename useMeta
to useHead
(#4066)
This commit is contained in:
parent
7054b9849f
commit
e90b8c28d1
@ -198,13 +198,13 @@ If you want to use the new Nuxt composables (such as `useNuxtApp` or `useRuntime
|
|||||||
Although a compatibility interface is provided via `nuxtApp.vueApp` you should avoid registering plugins, directives, mixins or components this way without adding your own logic to ensure they are not installed more than once, or this may cause a memory leak.
|
Although a compatibility interface is provided via `nuxtApp.vueApp` you should avoid registering plugins, directives, mixins or components this way without adding your own logic to ensure they are not installed more than once, or this may cause a memory leak.
|
||||||
::
|
::
|
||||||
|
|
||||||
## New `useMeta` (optional)
|
## New `useHead` (optional)
|
||||||
|
|
||||||
Nuxt Bridge provides a new Nuxt 3 meta API that can be accessed with a new `useMeta` composable.
|
Nuxt Bridge provides a new Nuxt 3 meta API that can be accessed with a new `useHead` composable.
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<script setup>
|
<script setup>
|
||||||
useMeta({
|
useHead({
|
||||||
title: 'My Nuxt App',
|
title: 'My Nuxt App',
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -222,10 +222,10 @@ export default defineNuxtConfig({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
This `useMeta` composable uses `@vueuse/head` under the hood (rather than `vue-meta`) to manipulate your `<head>`.
|
This `useHead` composable uses `@vueuse/head` under the hood (rather than `vue-meta`) to manipulate your `<head>`.
|
||||||
Accordingly, we recommend not to use both the native Nuxt 2 `head()` properties as well as `useMeta`, as they may conflict.
|
Accordingly, we recommend not to use both the native Nuxt 2 `head()` properties as well as `useHead`, as they may conflict.
|
||||||
|
|
||||||
For more information on how to use this composable, see [the docs](/docs/usage/meta-tags#usemeta-composable).
|
For more information on how to use this composable, see [the docs](/docs/usage/meta-tags#usehead-composable).
|
||||||
|
|
||||||
## Feature Flags
|
## Feature Flags
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ export default defineNuxtConfig({
|
|||||||
// Use Vite as the bundler instead of webpack 4
|
// Use Vite as the bundler instead of webpack 4
|
||||||
// vite: true,
|
// vite: true,
|
||||||
|
|
||||||
// Enable Nuxt 3 compatible useMeta
|
// Enable Nuxt 3 compatible useHead
|
||||||
// meta: true,
|
// meta: true,
|
||||||
|
|
||||||
// -- Default features --
|
// -- Default features --
|
||||||
|
@ -250,12 +250,12 @@ title.value = 'new title'
|
|||||||
Be careful not to use both `useNuxt2Meta()` and the Options API `head()` within the same component, as behavior may be unpredictable.
|
Be careful not to use both `useNuxt2Meta()` and the Options API `head()` within the same component, as behavior may be unpredictable.
|
||||||
::
|
::
|
||||||
|
|
||||||
Nuxt Bridge also provides a Nuxt 3-compatible meta implementation that can be accessed with the `useMeta` composable.
|
Nuxt Bridge also provides a Nuxt 3-compatible meta implementation that can be accessed with the `useHead` composable.
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
<script setup>
|
<script setup>
|
||||||
- import { useMeta } from '@nuxtjs/composition-api'
|
- import { useMeta } from '@nuxtjs/composition-api'
|
||||||
useMeta({
|
useHead({
|
||||||
title: 'My Nuxt App',
|
title: 'My Nuxt App',
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -272,6 +272,6 @@ export default defineNuxtConfig({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
This `useMeta` composable uses `@vueuse/head` under the hood (rather than `vue-meta`) to manipulate your `<head>`. Accordingly, it is recommended not to use both the native Nuxt 2 `head()` properties as well as `useMeta`, as they may conflict.
|
This `useHead` composable uses `@vueuse/head` under the hood (rather than `vue-meta`) to manipulate your `<head>`. Accordingly, it is recommended not to use both the native Nuxt 2 `head()` properties as well as `useHead`, as they may conflict.
|
||||||
|
|
||||||
For more information on how to use this composable, see [the Nuxt 3 docs](/docs/usage/meta-tags#usemeta-composable).
|
For more information on how to use this composable, see [the Nuxt 3 docs](/docs/usage/meta-tags#usehead-composable).
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
You can customize the meta tags for your site through several different ways:
|
You can customize the meta tags for your site through several different ways:
|
||||||
|
|
||||||
## `useMeta` Composable
|
## `useHead` Composable
|
||||||
|
|
||||||
Within your `setup` function, you can call `useMeta` with an object of meta properties with keys corresponding to meta tags: `title`, `base`, `script`, `style`, `meta` and `link`, as well as `htmlAttrs` and `bodyAttrs`. Alternatively, you can pass a function returning the object for reactive metadata.
|
Within your `setup` function, you can call `useHead` with an object of meta properties with keys corresponding to meta tags: `title`, `base`, `script`, `style`, `meta` and `link`, as well as `htmlAttrs` and `bodyAttrs`. Alternatively, you can pass a function returning the object for reactive metadata.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
export default {
|
export default {
|
||||||
setup () {
|
setup () {
|
||||||
useMeta({
|
useHead({
|
||||||
meta: [
|
meta: [
|
||||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1' }
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1' }
|
||||||
],
|
],
|
||||||
@ -63,7 +63,7 @@ export default {
|
|||||||
|
|
||||||
## Example: usage with definePageMeta
|
## Example: usage with definePageMeta
|
||||||
|
|
||||||
You can use `definePageMeta` along with `useMeta` to set metadata based on the current route.
|
You can use `definePageMeta` along with `useHead` to set metadata based on the current route.
|
||||||
|
|
||||||
For example, to include the page title alongside your app name, first define your page title:
|
For example, to include the page title alongside your app name, first define your page title:
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ And then in your layout file:
|
|||||||
<script setup>
|
<script setup>
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
useMeta({
|
useHead({
|
||||||
title: computed(() => `App Name - ${route.meta.title}`)
|
title: computed(() => `App Name - ${route.meta.title}`)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
Nuxt 3 provides several different ways to manage your meta tags.
|
Nuxt 3 provides several different ways to manage your meta tags.
|
||||||
|
|
||||||
1. Through your `nuxt.config`.
|
1. Through your `nuxt.config`.
|
||||||
1. Through the `useMeta` [composable](/docs/usage/meta-tags#usemeta-composable)
|
1. Through the `useHead` [composable](/docs/usage/meta-tags#usehead-composable)
|
||||||
1. Through [global meta components](/docs/usage/meta-tags#meta-components)
|
1. Through [global meta components](/docs/usage/meta-tags#meta-components)
|
||||||
|
|
||||||
You can customize `title`, `base`, `script`, `style`, `meta`, `link`, `htmlAttrs` and `bodyAttrs`.
|
You can customize `title`, `base`, `script`, `style`, `meta`, `link`, `htmlAttrs` and `bodyAttrs`.
|
||||||
@ -17,9 +17,9 @@ Nuxt currently uses [`vueuse/head`](https://github.com/vueuse/head) to manage yo
|
|||||||
## Migration
|
## Migration
|
||||||
|
|
||||||
1. In your `nuxt.config`, rename `head` to `meta`. Consider moving this shared meta configuration into your `app.vue` instead. (Note that objects no longer have a `hid` key for deduplication.)
|
1. In your `nuxt.config`, rename `head` to `meta`. Consider moving this shared meta configuration into your `app.vue` instead. (Note that objects no longer have a `hid` key for deduplication.)
|
||||||
1. In your components, rename your `head` option to `meta`. If you need to access the component state, you should migrate to using `useMeta`. You might also consider using the built-in meta-components.
|
1. If you need to access the component state with `head`, you should migrate to using `useHead`. You might also consider using the built-in meta-components.
|
||||||
|
|
||||||
### Example: `useMeta`
|
### Example: `useHead`
|
||||||
|
|
||||||
::code-group
|
::code-group
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ const title = ref('My App')
|
|||||||
const description = ref('My App Description')
|
const description = ref('My App Description')
|
||||||
|
|
||||||
// This will be reactive even you change title/description above
|
// This will be reactive even you change title/description above
|
||||||
useMeta({
|
useHead({
|
||||||
title,
|
title,
|
||||||
meta: [{
|
meta: [{
|
||||||
name: 'description',
|
name: 'description',
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
template: Example
|
template: Example
|
||||||
---
|
---
|
||||||
|
|
||||||
# useMeta
|
# useHead
|
||||||
|
|
||||||
This example shows how to use `useMeta` and Nuxt built-in components to bind meta data to the head of the page.
|
This example shows how to use `useHead` and Nuxt built-in components to bind meta data to the head of the page.
|
||||||
|
|
||||||
::alert{type=info icon=👉}
|
::alert{type=info icon=👉}
|
||||||
Learn more about [meta tags](/docs/usage/meta-tags).
|
Learn more about [meta tags](/docs/usage/meta-tags).
|
||||||
::
|
::
|
||||||
|
|
||||||
::sandbox{repo="nuxt/framework" branch="main" dir="examples/composables/use-meta" file="app.vue"}
|
::sandbox{repo="nuxt/framework" branch="main" dir="examples/composables/use-head" file="app.vue"}
|
@ -8,7 +8,7 @@
|
|||||||
| `use-async-data` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-async-data) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-async-data?file=app.vue&terminal=dev) |
|
| `use-async-data` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-async-data) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-async-data?file=app.vue&terminal=dev) |
|
||||||
| `use-cookie` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-cookie) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-cookie?file=app.vue&terminal=dev) |
|
| `use-cookie` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-cookie) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-cookie?file=app.vue&terminal=dev) |
|
||||||
| `use-fetch` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-fetch) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-fetch?file=app.vue&terminal=dev) |
|
| `use-fetch` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-fetch) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-fetch?file=app.vue&terminal=dev) |
|
||||||
| `use-meta` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-meta) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-meta?file=app.vue&terminal=dev) |
|
| `use-head` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-head) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-head?file=app.vue&terminal=dev) |
|
||||||
| `use-state` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-state) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-state?file=app.vue&terminal=dev) |
|
| `use-state` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/use-state) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-state?file=app.vue&terminal=dev) |
|
||||||
| `components` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/components) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/components?file=app.vue&terminal=dev) |
|
| `components` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/components) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/components?file=app.vue&terminal=dev) |
|
||||||
| `composables` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/composables) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/composables?file=app.vue&terminal=dev) |
|
| `composables` | [GitHub](https://github.com/nuxt/framework/tree/main/examples/composables) | [Play Online](https://stackblitz.com/github/nuxt/framework/tree/main/examples/composables?file=app.vue&terminal=dev) |
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<NuxtExampleLayout example="composables/use-meta">
|
<NuxtExampleLayout example="composables/use-head">
|
||||||
<div
|
<div
|
||||||
class="bg-gray-400/10 border-2 border-dashed border-gray-400/50 rounded-xl py-8 px-2 op-80"
|
class="bg-gray-400/10 border-2 border-dashed border-gray-400/50 rounded-xl py-8 px-2 op-80"
|
||||||
>
|
>
|
||||||
@ -26,7 +26,7 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
setup () {
|
setup () {
|
||||||
useMeta({
|
useHead({
|
||||||
bodyAttrs: {
|
bodyAttrs: {
|
||||||
class: 'test'
|
class: 'test'
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "example-use-meta",
|
"name": "example-use-head",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nuxi build",
|
"build": "nuxi build",
|
@ -1,6 +1,6 @@
|
|||||||
import { resolve } from 'pathe'
|
import { resolve } from 'pathe'
|
||||||
import { addTemplate, useNuxt, installModule } from '@nuxt/kit'
|
import { addTemplate, useNuxt, installModule } from '@nuxt/kit'
|
||||||
import metaModule from '../../nuxt3/src/meta/module'
|
import metaModule from '../../nuxt3/src/head/module'
|
||||||
import { distDir } from './dirs'
|
import { distDir } from './dirs'
|
||||||
|
|
||||||
const checkDocsMsg = 'Please see https://v3.nuxtjs.org for more information.'
|
const checkDocsMsg = 'Please see https://v3.nuxtjs.org for more information.'
|
||||||
@ -16,9 +16,9 @@ export const setupMeta = async (opts: SetupMetaOptions) => {
|
|||||||
if (opts.needsExplicitEnable) {
|
if (opts.needsExplicitEnable) {
|
||||||
const metaPath = addTemplate({
|
const metaPath = addTemplate({
|
||||||
filename: 'meta.mjs',
|
filename: 'meta.mjs',
|
||||||
getContents: () => `export const useMeta = () => console.warn('${msgPrefix} To use \`useMeta\`, please set \`bridge.meta\` to \`true\` in your \`nuxt.config\`. ${checkDocsMsg}')`
|
getContents: () => `export const useHead = () => console.warn('${msgPrefix} To use \`useHead\`, please set \`bridge.meta\` to \`true\` in your \`nuxt.config\`. ${checkDocsMsg}')`
|
||||||
})
|
})
|
||||||
nuxt.options.alias['#meta'] = metaPath.dst
|
nuxt.options.alias['#head'] = metaPath.dst
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ export const setupMeta = async (opts: SetupMetaOptions) => {
|
|||||||
throw new TypeError(`${msgPrefix} The head() function in \`nuxt.config\` has been deprecated and in Nuxt 3 will need to be moved to \`app.vue\`. ${checkDocsMsg}`)
|
throw new TypeError(`${msgPrefix} The head() function in \`nuxt.config\` has been deprecated and in Nuxt 3 will need to be moved to \`app.vue\`. ${checkDocsMsg}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const runtimeDir = resolve(distDir, 'runtime/meta')
|
const runtimeDir = resolve(distDir, 'runtime/head')
|
||||||
nuxt.options.alias['#meta'] = runtimeDir
|
nuxt.options.alias['#head'] = runtimeDir
|
||||||
|
|
||||||
await installModule(metaModule)
|
await installModule(metaModule)
|
||||||
}
|
}
|
||||||
|
1
packages/bridge/src/runtime/head
Symbolic link
1
packages/bridge/src/runtime/head
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../nuxt3/src/head/runtime/
|
@ -1 +0,0 @@
|
|||||||
../../../nuxt3/src/meta/runtime
|
|
@ -17,7 +17,7 @@
|
|||||||
},
|
},
|
||||||
"imports": {
|
"imports": {
|
||||||
"#app": "./dist/app/index.mjs",
|
"#app": "./dist/app/index.mjs",
|
||||||
"#meta": "./dist/meta/runtime/index.mjs",
|
"#head": "./dist/head/runtime/index.mjs",
|
||||||
"#pages": "./dist/pages/runtime/index.mjs"
|
"#pages": "./dist/pages/runtime/index.mjs"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
|
@ -7,8 +7,8 @@ export * from './components'
|
|||||||
// eslint-disable-next-line import/no-restricted-paths
|
// eslint-disable-next-line import/no-restricted-paths
|
||||||
export type { PageMeta } from '../pages/runtime'
|
export type { PageMeta } from '../pages/runtime'
|
||||||
// eslint-disable-next-line import/no-restricted-paths
|
// eslint-disable-next-line import/no-restricted-paths
|
||||||
export type { MetaObject } from '../meta/runtime'
|
export type { MetaObject } from '../head/runtime'
|
||||||
export { useMeta } from '#meta'
|
export { useHead, useMeta } from '#head'
|
||||||
|
|
||||||
export const isVue2 = false
|
export const isVue2 = false
|
||||||
export const isVue3 = true
|
export const isVue3 = true
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { defineUnimportPreset, Preset } from 'unimport'
|
import { defineUnimportPreset, Preset } from 'unimport'
|
||||||
|
|
||||||
export const commonPresets: Preset[] = [
|
export const commonPresets: Preset[] = [
|
||||||
// #meta
|
// #head
|
||||||
defineUnimportPreset({
|
defineUnimportPreset({
|
||||||
from: '#meta',
|
from: '#head',
|
||||||
imports: [
|
imports: [
|
||||||
|
'useHead',
|
||||||
'useMeta'
|
'useMeta'
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
|
@ -5,7 +5,7 @@ import { loadNuxtConfig, LoadNuxtOptions, nuxtCtx, installModule, addComponent,
|
|||||||
// Temporary until finding better placement
|
// Temporary until finding better placement
|
||||||
/* eslint-disable import/no-restricted-paths */
|
/* eslint-disable import/no-restricted-paths */
|
||||||
import pagesModule from '../pages/module'
|
import pagesModule from '../pages/module'
|
||||||
import metaModule from '../meta/module'
|
import metaModule from '../head/module'
|
||||||
import componentsModule from '../components/module'
|
import componentsModule from '../components/module'
|
||||||
import autoImportsModule from '../auto-imports/module'
|
import autoImportsModule from '../auto-imports/module'
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
|
@ -13,16 +13,16 @@ export default defineNuxtModule({
|
|||||||
viewport: 'width=device-width, initial-scale=1'
|
viewport: 'width=device-width, initial-scale=1'
|
||||||
},
|
},
|
||||||
setup (options, nuxt) {
|
setup (options, nuxt) {
|
||||||
const runtimeDir = nuxt.options.alias['#meta'] || resolve(distDir, 'meta/runtime')
|
const runtimeDir = nuxt.options.alias['#head'] || resolve(distDir, 'head/runtime')
|
||||||
|
|
||||||
// Transpile @nuxt/meta and @vueuse/head
|
// Transpile @nuxt/meta and @vueuse/head
|
||||||
nuxt.options.build.transpile.push('@vueuse/head')
|
nuxt.options.build.transpile.push('@vueuse/head')
|
||||||
|
|
||||||
// Add #meta alias
|
// Add #head alias
|
||||||
nuxt.options.alias['#meta'] = runtimeDir
|
nuxt.options.alias['#head'] = runtimeDir
|
||||||
|
|
||||||
// Global meta
|
// Global meta
|
||||||
const globalMeta: MetaObject = defu(nuxt.options.meta, {
|
const globalMeta: MetaObject = defu(nuxt.options.app.head, {
|
||||||
meta: [
|
meta: [
|
||||||
{ charset: options.charset },
|
{ charset: options.charset },
|
||||||
{ name: 'viewport', content: options.viewport }
|
{ name: 'viewport', content: options.viewport }
|
@ -1,6 +1,6 @@
|
|||||||
import { defineComponent } from 'vue'
|
import { defineComponent } from 'vue'
|
||||||
import type { SetupContext } from 'vue'
|
import type { SetupContext } from 'vue'
|
||||||
import { useMeta } from './composables'
|
import { useHead } from './composables'
|
||||||
|
|
||||||
type Props = Readonly<Record<string, any>>
|
type Props = Readonly<Record<string, any>>
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ const removeUndefinedProps = (props: Props) =>
|
|||||||
Object.fromEntries(Object.entries(props).filter(([, value]) => value !== undefined))
|
Object.fromEntries(Object.entries(props).filter(([, value]) => value !== undefined))
|
||||||
|
|
||||||
const setupForUseMeta = (metaFactory: (props: Props, ctx: SetupContext) => Record<string, any>, renderChild?: boolean) => (props: Props, ctx: SetupContext) => {
|
const setupForUseMeta = (metaFactory: (props: Props, ctx: SetupContext) => Record<string, any>, renderChild?: boolean) => (props: Props, ctx: SetupContext) => {
|
||||||
useMeta(() => metaFactory({ ...removeUndefinedProps(props), ...ctx.attrs }, ctx))
|
useHead(() => metaFactory({ ...removeUndefinedProps(props), ...ctx.attrs }, ctx))
|
||||||
return () => renderChild ? ctx.slots.default?.() : null
|
return () => renderChild ? ctx.slots.default?.() : null
|
||||||
}
|
}
|
||||||
|
|
@ -11,7 +11,21 @@ import { useNuxtApp } from '#app'
|
|||||||
* Alternatively, for reactive meta state, you can pass in a function
|
* Alternatively, for reactive meta state, you can pass in a function
|
||||||
* that returns a meta object.
|
* that returns a meta object.
|
||||||
*/
|
*/
|
||||||
export function useMeta (meta: MetaObject | ComputedGetter<MetaObject>) {
|
export function useHead (meta: MetaObject | ComputedGetter<MetaObject>) {
|
||||||
const resolvedMeta = isFunction(meta) ? computed(meta) : meta
|
const resolvedMeta = isFunction(meta) ? computed(meta) : meta
|
||||||
useNuxtApp()._useMeta(resolvedMeta)
|
useNuxtApp()._useHead(resolvedMeta)
|
||||||
|
}
|
||||||
|
|
||||||
|
const _warned = {}
|
||||||
|
const warnOnce = (id: string, message: string) => {
|
||||||
|
if (!_warned[id]) {
|
||||||
|
console.warn(message)
|
||||||
|
_warned[id] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: remove useMeta support when Nuxt 3 is stable
|
||||||
|
/** @deprecated */
|
||||||
|
export function useMeta (meta: MetaObject | ComputedGetter<MetaObject>) {
|
||||||
|
warnOnce('useMeta', '[meta] useMeta has been renamed to useHead.')
|
||||||
|
return useHead(meta)
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
|
|
||||||
nuxtApp.vueApp.use(manager)
|
nuxtApp.vueApp.use(manager)
|
||||||
|
|
||||||
nuxtApp._useMeta = (meta: MetaObject) => manager.addMeta(meta)
|
nuxtApp._useHead = (meta: MetaObject) => manager.addMeta(meta)
|
||||||
|
|
||||||
if (process.client) {
|
if (process.client) {
|
||||||
const teleportTarget = document.createElement('div')
|
const teleportTarget = document.createElement('div')
|
@ -14,7 +14,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
headReady = true
|
headReady = true
|
||||||
})
|
})
|
||||||
|
|
||||||
nuxtApp._useMeta = (meta: MetaObject) => {
|
nuxtApp._useHead = (meta: MetaObject) => {
|
||||||
const headObj = ref(meta as any)
|
const headObj = ref(meta as any)
|
||||||
head.addHeadObjs(headObj)
|
head.addHeadObjs(headObj)
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
import { computed, getCurrentInstance } from 'vue'
|
import { computed, getCurrentInstance } from 'vue'
|
||||||
import * as Components from './components'
|
import * as Components from './components'
|
||||||
import { useMeta } from './composables'
|
import { useHead } from './composables'
|
||||||
import { defineNuxtPlugin, useNuxtApp } from '#app'
|
import { defineNuxtPlugin, useNuxtApp } from '#app'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import metaConfig from '#build/meta.config.mjs'
|
import metaConfig from '#build/meta.config.mjs'
|
||||||
@ -23,12 +23,12 @@ const metaMixin = {
|
|||||||
? computed(() => options.head(nuxtApp))
|
? computed(() => options.head(nuxtApp))
|
||||||
: options.head
|
: options.head
|
||||||
|
|
||||||
useMeta(source)
|
useHead(source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineNuxtPlugin((nuxtApp) => {
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
useMeta(metaConfig.globalMeta)
|
useHead(metaConfig.globalMeta)
|
||||||
|
|
||||||
nuxtApp.vueApp.mixin(metaMixin)
|
nuxtApp.vueApp.mixin(metaMixin)
|
||||||
|
|
@ -66,9 +66,48 @@ export default {
|
|||||||
*/
|
*/
|
||||||
cdnURL: {
|
cdnURL: {
|
||||||
$resolve: (val, get) => get('dev') ? null : val || null
|
$resolve: (val, get) => get('dev') ? null : val || null
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Set default configuration for `<head>` on every page.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```js
|
||||||
|
* app: {
|
||||||
|
* head: {
|
||||||
|
* meta: [
|
||||||
|
* // <meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
* { name: 'viewport', content: 'width=device-width, initial-scale=1' }
|
||||||
|
* ],
|
||||||
|
* script: [
|
||||||
|
* // <script src="https://myawesome-lib.js"></script>
|
||||||
|
* { src: 'https://awesome-lib.js' }
|
||||||
|
* ],
|
||||||
|
* link: [
|
||||||
|
* // <link rel="stylesheet" href="https://myawesome-lib.css">
|
||||||
|
* { rel: 'stylesheet', href: 'https://awesome-lib.css' }
|
||||||
|
* ],
|
||||||
|
* // please note that this is an area that is likely to change
|
||||||
|
* style: [
|
||||||
|
* // <style type="text/css">:root { color: red }</style>
|
||||||
|
* { children: ':root { color: red }', type: 'text/css' }
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @type {typeof import('../src/types/meta').MetaObject}
|
||||||
|
* @version 3
|
||||||
|
*/
|
||||||
|
head: {
|
||||||
|
$resolve: (val, get) => {
|
||||||
|
return defu(val, get('meta'), {
|
||||||
|
meta: [],
|
||||||
|
link: [],
|
||||||
|
style: [],
|
||||||
|
script: []
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* The path to a templated HTML file for rendering Nuxt responses.
|
* The path to a templated HTML file for rendering Nuxt responses.
|
||||||
* Uses `<srcDir>/app.html` if it exists or the Nuxt default template if not.
|
* Uses `<srcDir>/app.html` if it exists or the Nuxt default template if not.
|
||||||
@ -140,32 +179,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set default configuration for `<head>` on every page.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```js
|
|
||||||
* meta: {
|
|
||||||
* meta: [
|
|
||||||
* // <meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
* { name: 'viewport', content: 'width=device-width, initial-scale=1' }
|
|
||||||
* ],
|
|
||||||
* script: [
|
|
||||||
* // <script src="https://myawesome-lib.js"></script>
|
|
||||||
* { src: 'https://awesome-lib.js' }
|
|
||||||
* ],
|
|
||||||
* link: [
|
|
||||||
* // <link rel="stylesheet" href="https://myawesome-lib.css">
|
|
||||||
* { rel: 'stylesheet', href: 'https://awesome-lib.css' }
|
|
||||||
* ],
|
|
||||||
* // please note that this is an area that is likely to change
|
|
||||||
* style: [
|
|
||||||
* // <style type="text/css">:root { color: red }</style>
|
|
||||||
* { children: ':root { color: red }', type: 'text/css' }
|
|
||||||
* ]
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
* @type {typeof import('../src/types/meta').MetaObject}
|
* @type {typeof import('../src/types/meta').MetaObject}
|
||||||
* @version 3
|
* @version 3
|
||||||
|
* @deprecated - use `head` instead
|
||||||
*/
|
*/
|
||||||
meta: {
|
meta: {
|
||||||
meta: [],
|
meta: [],
|
||||||
|
@ -744,6 +744,15 @@ export default {
|
|||||||
* @version 3
|
* @version 3
|
||||||
*/
|
*/
|
||||||
publicRuntimeConfig: {
|
publicRuntimeConfig: {
|
||||||
$resolve: (val: Record<string, any> = {}, get) => ({ ...val, app: defu(val.app, get('app')) })
|
$resolve: (val: Record<string, any> = {}, get) => ({
|
||||||
|
...val,
|
||||||
|
app: {
|
||||||
|
baseURL: get('app.baseURL'),
|
||||||
|
buildAssetsDir: get('app.buildAssetsDir'),
|
||||||
|
assetsPath: get('app.assetsPath'),
|
||||||
|
cdnURL: get('app.cdnURL'),
|
||||||
|
...val.app || {},
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,18 @@ describe('pages', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('head tags', () => {
|
||||||
|
it('should render tags', async () => {
|
||||||
|
const html = await $fetch('/head')
|
||||||
|
expect(html).toContain('<title>Using a dynamic component</title>')
|
||||||
|
expect(html).not.toContain('<meta name="description" content="first">')
|
||||||
|
expect(html).toContain('<meta name="description" content="overriding with an inline useHead call">')
|
||||||
|
expect(html).toMatch(/<html[^>]*class="html-attrs-test"/)
|
||||||
|
expect(html).toMatch(/<body[^>]*class="body-attrs-test"/)
|
||||||
|
expect(html).toContain('script>console.log("works with useMeta too")</script>')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('navigate', () => {
|
describe('navigate', () => {
|
||||||
it('should redirect to index with navigateTo', async () => {
|
it('should redirect to index with navigateTo', async () => {
|
||||||
const html = await $fetch('/navigate-to/')
|
const html = await $fetch('/navigate-to/')
|
||||||
|
30
test/fixtures/basic/pages/head.vue
vendored
Normal file
30
test/fixtures/basic/pages/head.vue
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<script setup>
|
||||||
|
useHead({
|
||||||
|
bodyAttrs: {
|
||||||
|
class: 'body-attrs-test'
|
||||||
|
},
|
||||||
|
meta: [{ name: 'description', content: 'first' }]
|
||||||
|
})
|
||||||
|
useHead({ meta: [{ name: 'description', content: 'overriding with an inline useHead call' }] })
|
||||||
|
useMeta({ script: [{ children: 'console.log("works with useMeta too")' }] })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
head () {
|
||||||
|
return {
|
||||||
|
htmlAttrs: {
|
||||||
|
class: 'html-attrs-test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Head>
|
||||||
|
<Title>Using a dynamic component</Title>
|
||||||
|
</Head>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -10895,9 +10895,9 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"example-use-meta@workspace:examples/composables/use-meta":
|
"example-use-head@workspace:examples/composables/use-head":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "example-use-meta@workspace:examples/composables/use-meta"
|
resolution: "example-use-head@workspace:examples/composables/use-head"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nuxt/ui": "npm:@nuxt/ui-edge@latest"
|
"@nuxt/ui": "npm:@nuxt/ui-edge@latest"
|
||||||
nuxt3: latest
|
nuxt3: latest
|
||||||
|
Loading…
Reference in New Issue
Block a user