mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-13 09:33:54 +00:00
perf(nuxt): add tree-shaken useServerSeoMeta
composable (#18476)
This commit is contained in:
parent
eac787eb48
commit
f711046171
@ -70,19 +70,21 @@ useHead({
|
|||||||
::ReadMore{link="/docs/api/composables/use-head"}
|
::ReadMore{link="/docs/api/composables/use-head"}
|
||||||
::
|
::
|
||||||
|
|
||||||
## Composable: `useSeoMeta`
|
## Composable: `useSeoMeta` and `useServerSeoMeta`
|
||||||
|
|
||||||
The `useSeoMeta` composable lets you define your site's SEO meta tags as a flat object with full TypeScript support.
|
The `useSeoMeta` and `useServerSeoMeta` composables let you define your site's SEO meta tags as a flat object with full TypeScript support.
|
||||||
|
|
||||||
This helps you avoid typos and common mistakes, such as using `name` instead of `property`.
|
This helps you avoid typos and common mistakes, such as using `name` instead of `property`.
|
||||||
|
|
||||||
|
In most instances, the meta does not need to be reactive as robots will only scan the initial load. So we recommend using `useServerSeoMeta` as a performance-focused utility that will not do anything (or return a `head` object) on the client.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
#### Simple
|
#### Simple
|
||||||
|
|
||||||
```vue{}[app.vue]
|
```vue{}[app.vue]
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
useSeoMeta({
|
useServerSeoMeta({
|
||||||
title: 'My Amazing Site',
|
title: 'My Amazing Site',
|
||||||
ogTitle: 'My Amazing Site',
|
ogTitle: 'My Amazing Site',
|
||||||
description: 'This is my amazing site, let me tell you all about it.',
|
description: 'This is my amazing site, let me tell you all about it.',
|
||||||
@ -101,7 +103,7 @@ use the computed getter syntax, the same as `useHead`.
|
|||||||
```vue{}[app.vue]
|
```vue{}[app.vue]
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const data = useFetch(() => $fetch('/api/example'))
|
const data = useFetch(() => $fetch('/api/example'))
|
||||||
useSeoMeta({
|
useServerSeoMeta({
|
||||||
ogTitle: () => `${data.value?.title} - My Site`,
|
ogTitle: () => `${data.value?.title} - My Site`,
|
||||||
description: () => data.value?.description,
|
description: () => data.value?.description,
|
||||||
ogDescription: () => data.value?.description,
|
ogDescription: () => data.value?.description,
|
||||||
@ -109,21 +111,6 @@ useSeoMeta({
|
|||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Client-side Optimization
|
|
||||||
|
|
||||||
In most instances, the meta does not need to be reactive as robots will only scan the initial load.
|
|
||||||
|
|
||||||
The composable itself is ~2kB, so you may consider only using it on the server and having it be tree-shaken from the client bundle.
|
|
||||||
|
|
||||||
```vue{}[app.vue]
|
|
||||||
<script setup lang="ts">
|
|
||||||
// only run on the server or in development mode
|
|
||||||
if (process.dev || process.server) {
|
|
||||||
useSeoMeta({ description: () => myDescription.value })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
::ReadMore{link="https://unhead.harlanzw.com/guide/guides/useseometa"}
|
::ReadMore{link="https://unhead.harlanzw.com/guide/guides/useseometa"}
|
||||||
::
|
::
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { resolve } from 'pathe'
|
import { resolve } from 'pathe'
|
||||||
import { addComponent, addImportsSources, addPlugin, defineNuxtModule } from '@nuxt/kit'
|
import { addComponent, addPlugin, defineNuxtModule } from '@nuxt/kit'
|
||||||
import { distDir } from '../dirs'
|
import { distDir } from '../dirs'
|
||||||
|
|
||||||
const components = ['NoScript', 'Link', 'Base', 'Title', 'Meta', 'Style', 'Head', 'Html', 'Body']
|
const components = ['NoScript', 'Link', 'Base', 'Title', 'Meta', 'Style', 'Head', 'Html', 'Body']
|
||||||
@ -17,13 +17,6 @@ export default defineNuxtModule({
|
|||||||
// Add #head alias
|
// Add #head alias
|
||||||
nuxt.options.alias['#head'] = runtimeDir
|
nuxt.options.alias['#head'] = runtimeDir
|
||||||
|
|
||||||
addImportsSources({
|
|
||||||
from: '@vueuse/head',
|
|
||||||
imports: [
|
|
||||||
'useSeoMeta'
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
// Register components
|
// Register components
|
||||||
const componentsPath = resolve(runtimeDir, 'components')
|
const componentsPath = resolve(runtimeDir, 'components')
|
||||||
for (const componentName of components) {
|
for (const componentName of components) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { HeadEntryOptions, UseHeadInput, ActiveHeadEntry } from '@vueuse/head'
|
import type { HeadEntryOptions, UseHeadInput, ActiveHeadEntry } from '@vueuse/head'
|
||||||
import type { HeadAugmentations } from '@nuxt/schema'
|
import type { HeadAugmentations } from '@nuxt/schema'
|
||||||
|
import { useSeoMeta as _useSeoMeta } from '@vueuse/head'
|
||||||
import { useNuxtApp } from '#app'
|
import { useNuxtApp } from '#app'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,3 +13,27 @@ import { useNuxtApp } from '#app'
|
|||||||
export function useHead<T extends HeadAugmentations> (input: UseHeadInput<T>, options?: HeadEntryOptions): ActiveHeadEntry<UseHeadInput<T>> | void {
|
export function useHead<T extends HeadAugmentations> (input: UseHeadInput<T>, options?: HeadEntryOptions): ActiveHeadEntry<UseHeadInput<T>> | void {
|
||||||
return useNuxtApp()._useHead(input, options)
|
return useNuxtApp()._useHead(input, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `useSeoMeta` composable lets you define your site's SEO meta tags
|
||||||
|
* as a flat object with full TypeScript support.
|
||||||
|
*
|
||||||
|
* This helps you avoid typos and common mistakes, such as using `name`
|
||||||
|
* instead of `property`.
|
||||||
|
*
|
||||||
|
* It is advised to use `useServerSeoMeta` unless you _need_ client-side
|
||||||
|
* rendering of your SEO meta tags.
|
||||||
|
*/
|
||||||
|
export const useSeoMeta: typeof _useSeoMeta = (meta) => {
|
||||||
|
return _useSeoMeta(meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `useServerSeoMeta` composable is identical to `useSeoMeta` except that
|
||||||
|
* it will have no effect (and will return nothing) if called on the client.
|
||||||
|
*/
|
||||||
|
export const useServerSeoMeta: typeof _useSeoMeta = (meta) => {
|
||||||
|
if (process.server) {
|
||||||
|
return _useSeoMeta(meta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,7 +6,9 @@ const commonPresets: InlinePreset[] = [
|
|||||||
defineUnimportPreset({
|
defineUnimportPreset({
|
||||||
from: '#head',
|
from: '#head',
|
||||||
imports: [
|
imports: [
|
||||||
'useHead'
|
'useHead',
|
||||||
|
'useSeoMeta',
|
||||||
|
'useServerSeoMeta'
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
// vue-demi (mocked)
|
// vue-demi (mocked)
|
||||||
|
Loading…
Reference in New Issue
Block a user