Modo de vista previa
Nota: Esta característica ha sido reemplazada por Modo borrador.
Ejemplos
- Ejemplo con WordPress (Demo)
- Ejemplo con DatoCMS (Demo)
- Ejemplo con TakeShape (Demo)
- Ejemplo con Sanity (Demo)
- Ejemplo con Prismic (Demo)
- Ejemplo con Contentful (Demo)
- Ejemplo con Strapi (Demo)
- Ejemplo con Prepr (Demo)
- Ejemplo con Agility CMS (Demo)
- Ejemplo con Cosmic (Demo)
- Ejemplo con ButterCMS (Demo)
- Ejemplo con Storyblok (Demo)
- Ejemplo con GraphCMS (Demo)
- Ejemplo con Kontent (Demo)
- Ejemplo con Umbraco Heartcore (Demo)
- Ejemplo con Plasmic (Demo)
- Ejemplo con Enterspeed (Demo)
- Ejemplo con Makeswift (Demo)
En la documentación de Páginas y la documentación de Obtención de datos, explicamos cómo prerrenderizar una página en tiempo de compilación (Generación estática) usando getStaticProps
y getStaticPaths
.
La Generación estática es útil cuando tus páginas obtienen datos de un CMS headless. Sin embargo, no es ideal cuando estás escribiendo un borrador en tu CMS headless y quieres previsualizarlo inmediatamente en tu página. En este caso, necesitarías que Next.js renderice estas páginas en tiempo de solicitud en lugar de tiempo de compilación, y que obtenga el contenido del borrador en lugar del contenido publicado. Querrías que Next.js evite la Generación estática solo para este caso específico.
Next.js tiene una característica llamada Modo de vista previa que resuelve este problema. A continuación, se indican las instrucciones para usarlo.
Paso 1: Crear y acceder a una ruta API de vista previa
Consulta primero la documentación de Rutas API si no estás familiarizado con las Rutas API de Next.js.
Primero, crea una ruta API de vista previa. Puede tener cualquier nombre, por ejemplo pages/api/preview.js
(o .ts
si usas TypeScript).
En esta ruta API, necesitas llamar a setPreviewData
en el objeto de respuesta. El argumento para setPreviewData
debe ser un objeto, y este puede ser usado por getStaticProps
(más sobre esto más adelante). Por ahora, usaremos {}
.
export default function handler(req, res) {
// ...
res.setPreviewData({})
// ...
}
res.setPreviewData
establece algunas cookies en el navegador que activan el modo de vista previa. Cualquier solicitud a Next.js que contenga estas cookies se considerará en modo de vista previa, y el comportamiento para páginas generadas estáticamente cambiará (más sobre esto más adelante).
Puedes probar esto manualmente creando una ruta API como la siguiente y accediendo a ella manualmente desde tu navegador:
// Ejemplo simple para probarlo manualmente desde tu navegador.
export default function handler(req, res) {
res.setPreviewData({})
res.end('Modo de vista previa activado')
}
Si abres las herramientas de desarrollador de tu navegador y visitas /api/preview
, notarás que las cookies __prerender_bypass
y __next_preview_data
se establecerán en esta solicitud.
Acceso seguro desde tu CMS headless
En la práctica, querrás llamar a esta ruta API de forma segura desde tu CMS headless. Los pasos específicos variarán según el CMS headless que uses, pero aquí hay algunos pasos comunes que podrías seguir.
Estos pasos asumen que el CMS headless que usas admite la configuración de URLs de vista previa personalizadas. Si no es así, aún puedes usar este método para proteger tus URLs de vista previa, pero necesitarás construir y acceder a la URL de vista previa manualmente.
Primero, debes crear una cadena de token secreto usando un generador de tokens de tu elección. Este secreto solo lo conocerán tu aplicación Next.js y tu CMS headless. Este secreto evita que personas que no tienen acceso a tu CMS accedan a las URLs de vista previa.
Segundo, si tu CMS headless admite configurar URLs de vista previa personalizadas, especifica lo siguiente como la URL de vista previa. Esto asume que tu ruta API de vista previa está ubicada en pages/api/preview.js
.
https://<tu-sitio>/api/preview?secret=<token>&slug=<ruta>
<tu-sitio>
debe ser tu dominio de despliegue.<token>
debe ser reemplazado con el token secreto que generaste.<ruta>
debe ser la ruta de la página que quieres previsualizar. Si quieres previsualizar/posts/foo
, entonces debes usar&slug=/posts/foo
.
Tu CMS headless podría permitirte incluir una variable en la URL de vista previa para que <ruta>
pueda establecerse dinámicamente según los datos del CMS, así: &slug=/posts/{entry.fields.slug}
Finalmente, en la ruta API de vista previa:
- Verifica que el secreto coincida y que exista el parámetro
slug
(si no, la solicitud debe fallar). - Llama a
res.setPreviewData
. - Luego redirige el navegador a la ruta especificada por
slug
. (El siguiente ejemplo usa una redirección 307).
export default async (req, res) => {
// Verifica el secreto y los parámetros
// Este secreto solo debe ser conocido por esta ruta API y el CMS
if (req.query.secret !== 'MI_TOKEN_SECRETO' || !req.query.slug) {
return res.status(401).json({ message: 'Token inválido' })
}
// Consulta el CMS headless para verificar si existe el `slug` proporcionado
// getPostBySlug implementaría la lógica necesaria para consultar el CMS headless
const post = await getPostBySlug(req.query.slug)
// Si el slug no existe, evita que se active el modo de vista previa
if (!post) {
return res.status(401).json({ message: 'Slug inválido' })
}
// Activa el Modo de vista previa estableciendo las cookies
res.setPreviewData({})
// Redirige a la ruta del post obtenido
// No redirigimos a req.query.slug para evitar vulnerabilidades de redirección abierta
res.redirect(post.slug)
}
Si tiene éxito, el navegador será redirigido a la ruta que deseas previsualizar con las cookies del modo de vista previa establecidas.
Paso 2: Actualizar getStaticProps
El siguiente paso es actualizar getStaticProps
para que admita el modo de vista previa.
Si solicitas una página que tiene getStaticProps
con las cookies del modo de vista previa establecidas (a través de res.setPreviewData
), entonces getStaticProps
se llamará en tiempo de solicitud (en lugar de tiempo de compilación).
Además, se llamará con un objeto context
donde:
context.preview
serátrue
.context.previewData
será el mismo que el argumento usado parasetPreviewData
.
export async function getStaticProps(context) {
// Si solicitas esta página con las cookies del modo de vista previa establecidas:
//
// - context.preview será true
// - context.previewData será el mismo que
// el argumento usado para `setPreviewData`.
}
Usamos res.setPreviewData({})
en la ruta API de vista previa, por lo que context.previewData
será {}
. Puedes usar esto para pasar información de sesión desde la ruta API de vista previa a getStaticProps
si es necesario.
Si también usas getStaticPaths
, entonces context.params
también estará disponible.
Obtener datos de vista previa
Puedes actualizar getStaticProps
para obtener datos diferentes según context.preview
y/o context.previewData
.
Por ejemplo, tu CMS headless podría tener un endpoint API diferente para posts en borrador. Si es así, puedes usar context.preview
para modificar la URL del endpoint API como se muestra a continuación:
export async function getStaticProps(context) {
// Si context.preview es true, añade "/preview" al endpoint API
// para solicitar datos de borrador en lugar de datos publicados. Esto variará
// según el CMS headless que uses.
const res = await fetch(`https://.../${context.preview ? 'preview' : ''}`)
// ...
}
¡Eso es todo! Si accedes a la ruta API de vista previa (con secret
y slug
) desde tu CMS headless o manualmente, ahora deberías poder ver el contenido de vista previa. Y si actualizas tu borrador sin publicarlo, deberías poder previsualizar el borrador.
Configura esto como la URL de vista previa en tu CMS headless o accede manualmente, y deberías poder ver la vista previa.
https://<tu-sitio>/api/preview?secret=<token>&slug=<ruta>
Más detalles
Bueno saber: durante el renderizado,
next/router
expone una banderaisPreview
, consulta la documentación del objeto router para más información.
Especificar la duración del Modo de vista previa
setPreviewData
acepta un segundo parámetro opcional que debe ser un objeto de opciones. Acepta las siguientes claves:
maxAge
: Especifica el número (en segundos) que durará la sesión de vista previa.path
: Especifica la ruta bajo la cual se aplicará la cookie. Por defecto es/
, lo que activa el modo de vista previa para todas las rutas.
setPreviewData(data, {
maxAge: 60 * 60, // Las cookies del modo de vista previa expiran en 1 hora
path: '/about', // Las cookies del modo de vista previa se aplican a rutas con /about
})
Limpiar las cookies del Modo de vista previa
Por defecto, no se establece una fecha de expiración para las cookies del Modo de vista previa, por lo que la sesión de vista previa termina cuando se cierra el navegador.
Para limpiar las cookies del Modo de vista previa manualmente, crea una ruta API que llame a clearPreviewData()
:
export default function handler(req, res) {
res.clearPreviewData({})
}
Luego, envía una solicitud a /api/clear-preview-mode-cookies
para invocar la Ruta API. Si llamas a esta ruta usando next/link
, debes pasar prefetch={false}
para evitar llamar a clearPreviewData
durante la precarga de enlaces.
Si se especificó una ruta en la llamada a setPreviewData
, debes pasar la misma ruta a clearPreviewData
:
export default function handler(req, res) {
const { path } = req.query
res.clearPreviewData({ path })
}
Límites de tamaño de previewData
Puedes pasar un objeto a setPreviewData
y que esté disponible en getStaticProps
. Sin embargo, como los datos se almacenarán en una cookie, hay un límite de tamaño. Actualmente, los datos de vista previa están limitados a 2KB.
Funciona con getServerSideProps
El modo de vista previa también funciona con getServerSideProps
. También estará disponible en el objeto context
que contiene preview
y previewData
.
Bueno saber: No debes establecer la cabecera
Cache-Control
cuando uses el Modo de vista previa porque no se puede omitir. En su lugar, recomendamos usar ISR.
Funciona con Rutas API
Las Rutas API tendrán acceso a preview
y previewData
bajo el objeto de solicitud. Por ejemplo:
export default function myApiRoute(req, res) {
const isPreview = req.preview
const previewData = req.previewData
// ...
}
Único por cada next build
Tanto el valor de la cookie de bypass como la clave privada para encriptar previewData
cambian cuando se completa next build
. Esto asegura que la cookie de bypass no pueda ser adivinada.
Bueno saber: Para probar el Modo de vista previa localmente sobre HTTP, tu navegador necesitará permitir cookies de terceros y acceso al almacenamiento local.