Objeto Metadata y opciones de generateMetadata
Esta página cubre todas las opciones de Metadata basada en configuración con generateMetadata
y el objeto de metadatos estáticos.
import { Metadata } from 'next'
// Metadata estática
export const metadata: Metadata = {
title: '...',
}
// Metadata dinámica
export async function generateMetadata({ params }) {
return {
title: '...',
}
}
// Metadata estática
export const metadata = {
title: '...',
}
// Metadata dinámica
export async function generateMetadata({ params }) {
return {
title: '...',
}
}
Es bueno saber:
- Las exportaciones del objeto
metadata
y la funcióngenerateMetadata
solo son compatibles en Componentes de Servidor.- No puede exportar tanto el objeto
metadata
como la funcióngenerateMetadata
desde el mismo segmento de ruta.
El objeto metadata
Para definir metadatos estáticos, exporte un objeto Metadata
desde un archivo layout.js
o page.js
.
import { Metadata } from 'next'
export const metadata: Metadata = {
title: '...',
description: '...',
}
export default function Page() {}
export const metadata = {
title: '...',
description: '...',
}
export default function Page() {}
Consulte los Campos de Metadata para ver una lista completa de opciones compatibles.
Función generateMetadata
Los metadatos dinámicos que dependen de información dinámica, como los parámetros de ruta actuales, datos externos o metadata
en segmentos padres, pueden configurarse exportando una función generateMetadata
que devuelve un objeto Metadata
.
import { Metadata, ResolvingMetadata } from 'next'
type Props = {
params: { id: string }
searchParams: { [key: string]: string | string[] | undefined }
}
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
// leer parámetros de ruta
const id = params.id
// obtener datos
const product = await fetch(`https://.../${id}`).then((res) => res.json())
// opcionalmente acceder y extender (en lugar de reemplazar) metadatos padres
const previousImages = (await parent).openGraph?.images || []
return {
title: product.title,
openGraph: {
images: ['/some-specific-page-image.jpg', ...previousImages],
},
}
}
export default function Page({ params, searchParams }: Props) {}
export async function generateMetadata({ params, searchParams }, parent) {
// leer parámetros de ruta
const id = params.id
// obtener datos
const product = await fetch(`https://.../${id}`).then((res) => res.json())
// opcionalmente acceder y extender (en lugar de reemplazar) metadatos padres
const previousImages = (await parent).openGraph?.images || []
return {
title: product.title,
openGraph: {
images: ['/some-specific-page-image.jpg', ...previousImages],
},
}
}
export default function Page({ params, searchParams }) {}
Parámetros
La función generateMetadata
acepta los siguientes parámetros:
-
props
- Un objeto que contiene los parámetros de la ruta actual:-
params
- Un objeto que contiene los parámetros de ruta dinámica desde el segmento raíz hasta el segmento donde se llama agenerateMetadata
. Ejemplos:Ruta URL params
app/shop/[slug]/page.js
/shop/1
{ slug: '1' }
app/shop/[tag]/[item]/page.js
/shop/1/2
{ tag: '1', item: '2' }
app/shop/[...slug]/page.js
/shop/1/2
{ slug: ['1', '2'] }
-
searchParams
- Un objeto que contiene los parámetros de búsqueda de la URL actual. Ejemplos:URL searchParams
/shop?a=1
{ a: '1' }
/shop?a=1&b=2
{ a: '1', b: '2' }
/shop?a=1&a=2
{ a: ['1', '2'] }
-
-
parent
- Una promesa de los metadatos resueltos de los segmentos de ruta padres.
Retornos
generateMetadata
debe devolver un objeto Metadata
que contenga uno o más campos de metadatos.
Es bueno saber:
- Si los metadatos no dependen de información en tiempo de ejecución, deben definirse usando el objeto estático
metadata
en lugar degenerateMetadata
.- Las solicitudes
fetch
se memorizan automáticamente para los mismos datos engenerateMetadata
,generateStaticParams
, Layouts, Pages y Server Components. Se puede usarcache
de React sifetch
no está disponible.searchParams
solo está disponible en segmentospage.js
.- Los métodos
redirect()
ynotFound()
de Next.js también se pueden usar dentro degenerateMetadata
.
Campos de Metadata
title
El atributo title
se usa para establecer el título del documento. Se puede definir como una cadena simple o un objeto de plantilla opcional.
String
export const metadata = {
title: 'Next.js',
}
<title>Next.js</title>
Template object
import { Metadata } from 'next'
export const metadata: Metadata = {
title: {
template: '...',
default: '...',
absolute: '...',
},
}
export const metadata = {
title: {
default: '...',
template: '...',
absolute: '...',
},
}
Default
title.default
se puede usar para proporcionar un título de respaldo a segmentos de ruta hijos que no definen un title
.
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: {
default: 'Acme',
},
}
import type { Metadata } from 'next'
export const metadata: Metadata = {}
// Output: <title>Acme</title>
Template
title.template
se puede usar para agregar un prefijo o sufijo a los titles
definidos en segmentos de ruta hijos.
import { Metadata } from 'next'
export const metadata: Metadata = {
title: {
template: '%s | Acme',
default: 'Acme', // se requiere un valor predeterminado al crear una plantilla
},
}
export const metadata = {
title: {
template: '%s | Acme',
default: 'Acme', // se requiere un valor predeterminado al crear una plantilla
},
}
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'About',
}
// Output: <title>About | Acme</title>
export const metadata = {
title: 'About',
}
// Output: <title>About | Acme</title>
Es bueno saber:
title.template
se aplica a segmentos de ruta hijos y no al segmento donde se define. Esto significa:
title.default
es requerido cuando agrega untitle.template
.title.template
definido enlayout.js
no se aplicará a untitle
definido en unpage.js
del mismo segmento de ruta.title.template
definido enpage.js
no tiene efecto porque una página siempre es el segmento terminal (no tiene segmentos de ruta hijos).
title.template
no tiene efecto si una ruta no ha definido untitle
otitle.default
.
Absolute
title.absolute
se puede usar para proporcionar un título que ignora title.template
establecido en segmentos padres.
import { Metadata } from 'next'
export const metadata: Metadata = {
title: {
template: '%s | Acme',
},
}
export const metadata = {
title: {
template: '%s | Acme',
},
}
import { Metadata } from 'next'
export const metadata: Metadata = {
title: {
absolute: 'About',
},
}
// Output: <title>About</title>
export const metadata = {
title: {
absolute: 'About',
},
}
// Output: <title>About</title>
Es bueno saber:
layout.js
title
(string) ytitle.default
definen el título predeterminado para segmentos hijos (que no definen su propiotitle
). Aumentarátitle.template
del segmento padre más cercano si existe.title.absolute
define el título predeterminado para segmentos hijos. Ignoratitle.template
de segmentos padres.title.template
define una nueva plantilla de título para segmentos hijos.
page.js
- Si una página no define su propio título, se usará el título resuelto del padre más cercano.
title
(string) define el título de la ruta. Aumentarátitle.template
del segmento padre más cercano si existe.title.absolute
define el título de la ruta. Ignoratitle.template
de segmentos padres.title.template
no tiene efecto enpage.js
porque una página siempre es el segmento terminal de una ruta.
description
export const metadata = {
description: 'The React Framework for the Web',
}
<meta name="description" content="The React Framework for the Web" />
Campos básicos
export const metadata = {
generator: 'Next.js',
applicationName: 'Next.js',
referrer: 'origin-when-cross-origin',
keywords: ['Next.js', 'React', 'JavaScript'],
authors: [{ name: 'Seb' }, { name: 'Josh', url: 'https://nextjs.org' }],
creator: 'Jiachi Liu',
publisher: 'Sebastian Markbåge',
formatDetection: {
email: false,
address: false,
telephone: false,
},
}
<meta name="application-name" content="Next.js" />
<meta name="author" content="Seb" />
<link rel="author" href="https://nextjs.org" />
<meta name="author" content="Josh" />
<meta name="generator" content="Next.js" />
<meta name="keywords" content="Next.js,React,JavaScript" />
<meta name="referrer" content="origin-when-cross-origin" />
<meta name="color-scheme" content="dark" />
<meta name="creator" content="Jiachi Liu" />
<meta name="publisher" content="Sebastian Markbåge" />
<meta name="format-detection" content="telephone=no, address=no, email=no" />
metadataBase
metadataBase
es una opción conveniente para establecer un prefijo de URL base para campos metadata
que requieren una URL completa.
metadataBase
permite que los camposmetadata
basados en URL definidos en el segmento de ruta actual y siguientes usen una ruta relativa en lugar de una URL absoluta que de otro modo sería requerida.- La ruta relativa del campo se combinará con
metadataBase
para formar una URL completa. - Si no se configura,
metadataBase
se rellena automáticamente con un valor predeterminado.
export const metadata = {
metadataBase: new URL('https://acme.com'),
alternates: {
canonical: '/',
languages: {
'en-US': '/en-US',
'de-DE': '/de-DE',
},
},
openGraph: {
images: '/og-image.png',
},
}
<link rel="canonical" href="https://acme.com" />
<link rel="alternate" hreflang="en-US" href="https://acme.com/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://acme.com/de-DE" />
<meta property="og:image" content="https://acme.com/og-image.png" />
Es bueno saber:
metadataBase
normalmente se establece en elapp/layout.js
raíz para aplicar a camposmetadata
basados en URL en todas las rutas.- Todos los campos
metadata
basados en URL que requieren URLs absolutas se pueden configurar con una opciónmetadataBase
.metadataBase
puede contener un subdominio, por ejemplo,https://app.acme.com
o una ruta base, por ejemplo,https://acme.com/start/from/here
.- Si un campo
metadata
proporciona una URL absoluta,metadataBase
se ignorará.- Usar una ruta relativa en un campo
metadata
basado en URL sin configurar unmetadataBase
causará un error de compilación.- Next.js normalizará barras diagonales duplicadas entre
metadataBase
(por ejemplo,https://acme.com/
) y un campo relativo (por ejemplo,/path
) a una sola barra (por ejemplo,https://acme.com/path
).
Valor predeterminado
Si no se configura, metadataBase
tiene un valor predeterminado:
- Cuando se detecta
VERCEL_URL
:https://${process.env.VERCEL_URL}
, de lo contrario, recurre ahttp://localhost:${process.env.PORT || 3000}
. - Al anular el valor predeterminado, recomendamos usar variables de entorno para calcular la URL. Esto permite configurar una URL para entornos de desarrollo local, staging y producción.
Composición de URL
La composición de URL favorece la intención del desarrollador sobre la semántica predeterminada de recorrido de directorios.
- Las barras diagonales finales entre
metadataBase
y camposmetadata
se normalizan. - Una ruta "absoluta" en un campo
metadata
(que normalmente reemplazaría toda la ruta de la URL) se trata como una ruta "relativa" (comenzando desde el final demetadataBase
).
Por ejemplo, dado el siguiente metadataBase
:
import { Metadata } from 'next'
export const metadata: Metadata = {
metadataBase: new URL('https://acme.com'),
}
export const metadata = {
metadataBase: new URL('https://acme.com'),
}
Cualquier campo metadata
que herede el metadataBase
anterior y establezca su propio valor se resolverá de la siguiente manera:
Campo metadata | URL resuelta |
---|---|
/ | https://acme.com |
./ | https://acme.com |
payments | https://acme.com/payments |
/payments | https://acme.com/payments |
./payments | https://acme.com/payments |
../payments | https://acme.com/payments |
https://beta.acme.com/payments | https://beta.acme.com/payments |
openGraph
export const metadata = {
openGraph: {
title: 'Next.js',
description: 'The React Framework for the Web',
url: 'https://nextjs.org',
siteName: 'Next.js',
images: [
{
url: 'https://nextjs.org/og.png', // Debe ser una URL absoluta
width: 800,
height: 600,
},
{
url: 'https://nextjs.org/og-alt.png', // Debe ser una URL absoluta
width: 1800,
height: 1600,
alt: 'Mi texto alternativo personalizado',
},
],
videos: [
{
url: 'https://nextjs.org/video.mp4', // Debe ser una URL absoluta
width: 800,
height: 600,
},
],
audio: [
{
url: 'https://nextjs.org/audio.mp3', // Debe ser una URL absoluta
},
],
locale: 'en_US',
type: 'website',
},
}
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:url" content="https://nextjs.org/" />
<meta property="og:site_name" content="Next.js" />
<meta property="og:locale" content="en_US" />
<meta property="og:image:url" content="https://nextjs.org/og.png" />
<meta property="og:image:width" content="800" />
<meta property="og:image:height" content="600" />
<meta property="og:image:url" content="https://nextjs.org/og-alt.png" />
<meta property="og:image:width" content="1800" />
<meta property="og:image:height" content="1600" />
<meta property="og:image:alt" content="Mi texto alternativo personalizado" />
<meta property="og:video" content="https://nextjs.org/video.mp4" />
<meta property="og:video:width" content="800" />
<meta property="og:video:height" content="600" />
<meta property="og:audio" content="https://nextjs.org/audio.mp3" />
<meta property="og:type" content="website" />
export const metadata = {
openGraph: {
title: 'Next.js',
description: 'The React Framework for the Web',
type: 'article',
publishedTime: '2023-01-01T00:00:00.000Z',
authors: ['Seb', 'Josh'],
},
}
<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2023-01-01T00:00:00.000Z" />
<meta property="article:author" content="Seb" />
<meta property="article:author" content="Josh" />
Nota importante:
- Puede ser más conveniente usar la API de Metadata basada en archivos para imágenes de Open Graph. En lugar de tener que sincronizar la exportación de configuración con archivos reales, la API basada en archivos generará automáticamente los metadatos correctos.
robots
import type { Metadata } from 'next'
export const metadata: Metadata = {
robots: {
index: false,
follow: true,
nocache: true,
googleBot: {
index: true,
follow: false,
noimageindex: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
}
<meta name="robots" content="noindex, follow, nocache" />
<meta
name="googlebot"
content="index, nofollow, noimageindex, max-video-preview:-1, max-image-preview:large, max-snippet:-1"
/>
icons
Nota importante: Recomendamos usar la API de Metadata basada en archivos para iconos cuando sea posible. En lugar de tener que sincronizar la exportación de configuración con archivos reales, la API basada en archivos generará automáticamente los metadatos correctos.
export const metadata = {
icons: {
icon: '/icon.png',
shortcut: '/shortcut-icon.png',
apple: '/apple-icon.png',
other: {
rel: 'apple-touch-icon-precomposed',
url: '/apple-touch-icon-precomposed.png',
},
},
}
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
rel="apple-touch-icon-precomposed"
href="/apple-touch-icon-precomposed.png"
/>
export const metadata = {
icons: {
icon: [
{ url: '/icon.png' },
new URL('/icon.png', 'https://example.com'),
{ url: '/icon-dark.png', media: '(prefers-color-scheme: dark)' },
],
shortcut: ['/shortcut-icon.png'],
apple: [
{ url: '/apple-icon.png' },
{ url: '/apple-icon-x3.png', sizes: '180x180', type: 'image/png' },
],
other: [
{
rel: 'apple-touch-icon-precomposed',
url: '/apple-touch-icon-precomposed.png',
},
],
},
}
<link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="icon" href="https://example.com/icon.png" />
<link rel="icon" href="/icon-dark.png" media="(prefers-color-scheme: dark)" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
rel="apple-touch-icon-precomposed"
href="/apple-touch-icon-precomposed.png"
/>
<link
rel="apple-touch-icon"
href="/apple-icon-x3.png"
sizes="180x180"
type="image/png"
/>
Nota importante: Las etiquetas meta
msapplication-*
ya no son compatibles en las versiones Chromium de Microsoft Edge, por lo que ya no son necesarias.
themeColor
Obsoleto: La opción
themeColor
enmetadata
está obsoleta a partir de Next.js 14. Por favor, use la configuraciónviewport
en su lugar.
manifest
Un manifiesto de aplicación web, como se define en la especificación de Manifiesto de Aplicación Web.
export const metadata = {
manifest: 'https://nextjs.org/manifest.json',
}
<link rel="manifest" href="https://nextjs.org/manifest.json" />
twitter
La especificación de Twitter se usa (sorprendentemente) para más que solo X (anteriormente conocido como Twitter).
Aprenda más sobre la referencia de marcado de Twitter Card.
export const metadata = {
twitter: {
card: 'summary_large_image',
title: 'Next.js',
description: 'The React Framework for the Web',
siteId: '1467726470533754880',
creator: '@nextjs',
creatorId: '1467726470533754880',
images: ['https://nextjs.org/og.png'], // Debe ser una URL absoluta
},
}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
export const metadata = {
twitter: {
card: 'app',
title: 'Next.js',
description: 'The React Framework for the Web',
siteId: '1467726470533754880',
creator: '@nextjs',
creatorId: '1467726470533754880',
images: {
url: 'https://nextjs.org/og.png',
alt: 'Next.js Logo',
},
app: {
name: 'twitter_app',
id: {
iphone: 'twitter_app://iphone',
ipad: 'twitter_app://ipad',
googleplay: 'twitter_app://googleplay',
},
url: {
iphone: 'https://iphone_url',
ipad: 'https://ipad_url',
},
},
},
}
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:card" content="app" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
<meta name="twitter:image:alt" content="Next.js Logo" />
<meta name="twitter:app:name:iphone" content="twitter_app" />
<meta name="twitter:app:id:iphone" content="twitter_app://iphone" />
<meta name="twitter:app:id:ipad" content="twitter_app://ipad" />
<meta name="twitter:app:id:googleplay" content="twitter_app://googleplay" />
<meta name="twitter:app:url:iphone" content="https://iphone_url" />
<meta name="twitter:app:url:ipad" content="https://ipad_url" />
<meta name="twitter:app:name:ipad" content="twitter_app" />
<meta name="twitter:app:name:googleplay" content="twitter_app" />
viewport
Obsoleto: La opción
viewport
enmetadata
está obsoleta a partir de Next.js 14. Por favor, use la configuraciónviewport
en su lugar.
verification
export const metadata = {
verification: {
google: 'google',
yandex: 'yandex',
yahoo: 'yahoo',
other: {
me: ['my-email', 'my-link'],
},
},
}
<meta name="google-site-verification" content="google" />
<meta name="y_key" content="yahoo" />
<meta name="yandex-verification" content="yandex" />
<meta name="me" content="my-email" />
<meta name="me" content="my-link" />
appleWebApp
export const metadata = {
itunes: {
appId: 'myAppStoreID',
appArgument: 'myAppArgument',
},
appleWebApp: {
title: 'Apple Web App',
statusBarStyle: 'black-translucent',
startupImage: [
'/assets/startup/apple-touch-startup-image-768x1004.png',
{
url: '/assets/startup/apple-touch-startup-image-1536x2008.png',
media: '(device-width: 768px) and (device-height: 1024px)',
},
],
},
}
<meta
name="apple-itunes-app"
content="app-id=myAppStoreID, app-argument=myAppArgument"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Apple Web App" />
<link
href="/assets/startup/apple-touch-startup-image-768x1004.png"
rel="apple-touch-startup-image"
/>
<link
href="/assets/startup/apple-touch-startup-image-1536x2008.png"
media="(device-width: 768px) and (device-height: 1024px)"
rel="apple-touch-startup-image"
/>
<meta
name="apple-mobile-web-app-status-bar-style"
content="black-translucent"
/>
alternates
export const metadata = {
alternates: {
canonical: 'https://nextjs.org',
languages: {
'en-US': 'https://nextjs.org/en-US',
'de-DE': 'https://nextjs.org/de-DE',
},
media: {
'only screen and (max-width: 600px)': 'https://nextjs.org/mobile',
},
types: {
'application/rss+xml': 'https://nextjs.org/rss',
},
},
}
<link rel="canonical" href="https://nextjs.org" />
<link rel="alternate" hreflang="en-US" href="https://nextjs.org/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://nextjs.org/de-DE" />
<link
rel="alternate"
media="only screen and (max-width: 600px)"
href="https://nextjs.org/mobile"
/>
<link
rel="alternate"
type="application/rss+xml"
href="https://nextjs.org/rss"
/>
appLinks
export const metadata = {
appLinks: {
ios: {
url: 'https://nextjs.org/ios',
app_store_id: 'app_store_id',
},
android: {
package: 'com.example.android/package',
app_name: 'app_name_android',
},
web: {
url: 'https://nextjs.org/web',
should_fallback: true,
},
},
}
<meta property="al:ios:url" content="https://nextjs.org/ios" />
<meta property="al:ios:app_store_id" content="app_store_id" />
<meta property="al:android:package" content="com.example.android/package" />
<meta property="al:android:app_name" content="app_name_android" />
<meta property="al:web:url" content="https://nextjs.org/web" />
<meta property="al:web:should_fallback" content="true" />
archives
Describe una colección de registros, documentos u otros materiales de interés histórico (fuente).
export const metadata = {
archives: ['https://nextjs.org/13'],
}
<link rel="archives" href="https://nextjs.org/13" />
assets
export const metadata = {
assets: ['https://nextjs.org/assets'],
}
<link rel="assets" href="https://nextjs.org/assets" />
bookmarks
export const metadata = {
bookmarks: ['https://nextjs.org/13'],
}
<link rel="bookmarks" href="https://nextjs.org/13" />
category
export const metadata = {
category: 'technology',
}
<meta name="category" content="technology" />
facebook
Puede conectar una aplicación de Facebook o una cuenta de Facebook a su página web para ciertos Plugins Sociales de Facebook Documentación de Facebook
Nota importante: Puede especificar appId o admins, pero no ambos.
export const metadata = {
facebook: {
appId: '12345678',
},
}
<meta property="fb:app_id" content="12345678" />
export const metadata = {
facebook: {
admins: '12345678',
},
}
<meta property="fb:admins" content="12345678" />
Si desea generar múltiples etiquetas meta fb:admins, puede usar un valor de array.
export const metadata = {
facebook: {
admins: ['12345678', '87654321'],
},
}
<meta property="fb:admins" content="12345678" />
<meta property="fb:admins" content="87654321" />
other
Todas las opciones de metadatos deberían estar cubiertas usando el soporte incorporado. Sin embargo, puede haber etiquetas meta personalizadas específicas para su sitio, o nuevas etiquetas meta recién lanzadas. Puede usar la opción other
para renderizar cualquier etiqueta meta personalizada.
export const metadata = {
other: {
custom: 'meta',
},
}
<meta name="custom" content="meta" />
Si desea generar múltiples etiquetas meta con la misma clave, puede usar un valor de array.
export const metadata = {
other: {
custom: ['meta1', 'meta2'],
},
}
<meta name="custom" content="meta1" /> <meta name="custom" content="meta2" />
Metadatos no admitidos
Los siguientes tipos de metadatos no tienen soporte incorporado actualmente. Sin embargo, aún pueden renderizarse en el layout o la página misma.
Metadatos | Recomendación |
---|---|
<meta http-equiv="..."> | Use encabezados HTTP apropiados mediante redirect() , Middleware, o Encabezados de Seguridad |
<base> | Renderice la etiqueta en el layout o la página misma. |
<noscript> | Renderice la etiqueta en el layout o la página misma. |
<style> | Más información sobre estilos en Next.js. |
<script> | Más información sobre uso de scripts. |
<link rel="stylesheet" /> | importe hojas de estilo directamente en el layout o la página misma. |
<link rel="preload /> | Use el método preload de ReactDOM |
<link rel="preconnect" /> | Use el método preconnect de ReactDOM |
<link rel="dns-prefetch" /> | Use el método prefetchDNS de ReactDOM |
Pistas de recursos (Resource hints)
El elemento <link>
tiene varias palabras clave rel
que pueden usarse para indicar al navegador que es probable que se necesite un recurso externo. El navegador usa esta información para aplicar optimizaciones de precarga según la palabra clave.
Aunque la API de Metadatos no admite directamente estas pistas, puede usar los nuevos métodos de ReactDOM
para insertarlas de forma segura en el <head>
del documento.
'use client'
import ReactDOM from 'react-dom'
export function PreloadResources() {
ReactDOM.preload('...', { as: '...' })
ReactDOM.preconnect('...', { crossOrigin: '...' })
ReactDOM.prefetchDNS('...')
return null
}
'use client'
import ReactDOM from 'react-dom'
export function PreloadResources() {
ReactDOM.preload('...', { as: '...' })
ReactDOM.preconnect('...', { crossOrigin: '...' })
ReactDOM.prefetchDNS('...')
return null
}
<link rel="preload">
Inicia la carga de un recurso temprano en el ciclo de vida del renderizado de la página (navegador). Documentación MDN.
ReactDOM.preload(href: string, options: { as: string })
<link rel="preload" href="..." as="..." />
<link rel="preconnect">
Inicia preventivamente una conexión a un origen. Documentación MDN.
ReactDOM.preconnect(href: string, options?: { crossOrigin?: string })
<link rel="preconnect" href="..." crossorigin />
<link rel="dns-prefetch">
Intenta resolver un nombre de dominio antes de que se soliciten los recursos. Documentación MDN.
ReactDOM.prefetchDNS(href: string)
<link rel="dns-prefetch" href="..." />
Nota importante:
- Estos métodos actualmente solo son compatibles con Componentes de Cliente (Client Components), que aún se renderizan en el servidor en la carga inicial de la página.
- Las funciones integradas de Next.js como
next/font
,next/image
ynext/script
manejan automáticamente las pistas de recursos relevantes.- React 18.3 aún no incluye definiciones de tipo para
ReactDOM.preload
,ReactDOM.preconnect
yReactDOM.preconnectDNS
. Puede usar// @ts-ignore
como solución temporal para evitar errores de tipo.
Tipos
Puede agregar seguridad de tipos a sus metadatos usando el tipo Metadata
. Si está utilizando el plugin de TypeScript incorporado en su IDE, no necesita agregar manualmente el tipo, pero aún puede hacerlo explícitamente si lo desea.
Objeto metadata
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Next.js',
}
Función generateMetadata
Función regular
import type { Metadata } from 'next'
export function generateMetadata(): Metadata {
return {
title: 'Next.js',
}
}
Función asíncrona
import type { Metadata } from 'next'
export async function generateMetadata(): Promise<Metadata> {
return {
title: 'Next.js',
}
}
Con props de segmento
import type { Metadata } from 'next'
type Props = {
params: { id: string }
searchParams: { [key: string]: string | string[] | undefined }
}
export function generateMetadata({ params, searchParams }: Props): Metadata {
return {
title: 'Next.js',
}
}
export default function Page({ params, searchParams }: Props) {}
Con metadatos padre
import type { Metadata, ResolvingMetadata } from 'next'
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
return {
title: 'Next.js',
}
}
Proyectos JavaScript
Para proyectos JavaScript, puede usar JSDoc para agregar seguridad de tipos.
/** @type {import("next").Metadata} */
export const metadata = {
title: 'Next.js',
}
Historial de versiones
Versión | Cambios |
---|---|
v13.2.0 | viewport , themeColor , y colorScheme obsoletos en favor de la configuración viewport . |
v13.2.0 | Se introdujeron metadata y generateMetadata . |