Режим предварительного просмотра (Preview Mode)
Примечание: Эта функция заменена Режимом черновика (Draft Mode).
Примеры
- Пример с WordPress (Демо)
- Пример с DatoCMS (Демо)
- Пример с TakeShape (Демо)
- Пример с Sanity (Демо)
- Пример с Prismic (Демо)
- Пример с Contentful (Демо)
- Пример с Strapi (Демо)
- Пример с Prepr (Демо)
- Пример с Agility CMS (Демо)
- Пример с Cosmic (Демо)
- Пример с ButterCMS (Демо)
- Пример с Storyblok (Демо)
- Пример с GraphCMS (Демо)
- Пример с Kontent (Демо)
- Пример с Umbraco Heartcore (Демо)
- Пример с Plasmic (Демо)
- Пример с Enterspeed (Демо)
- Пример с Makeswift (Демо)
В документации по страницам и документации по получению данных мы обсуждали, как предварительно отрендерить страницу во время сборки (Статическая генерация) с помощью getStaticProps
и getStaticPaths
.
Статическая генерация полезна, когда ваши страницы получают данные из headless CMS. Однако она не идеальна, когда вы пишете черновик в вашей headless CMS и хотите предварительно просмотреть его сразу на странице. В этом случае вам нужно, чтобы Next.js рендерил эти страницы во время запроса, а не во время сборки, и получал черновик вместо опубликованного контента. Вам нужно, чтобы Next.js обходил статическую генерацию только для этого конкретного случая.
Next.js предоставляет функцию Режим предварительного просмотра (Preview Mode), которая решает эту проблему. Вот инструкции по её использованию.
Шаг 1: Создание и доступ к API-маршруту предварительного просмотра
Сначала ознакомьтесь с документацией по API-маршрутам, если вы не знакомы с API-маршрутами Next.js.
Сначала создайте API-маршрут для предварительного просмотра. Он может иметь любое имя, например pages/api/preview.js
(или .ts
, если используется TypeScript).
В этом API-маршруте вам нужно вызвать setPreviewData
для объекта ответа. Аргумент для setPreviewData
должен быть объектом, и он может использоваться в getStaticProps
(подробнее об этом позже). Пока мы будем использовать {}
.
export default function handler(req, res) {
// ...
res.setPreviewData({})
// ...
}
res.setPreviewData
устанавливает некоторые куки в браузере, которые включают режим предварительного просмотра. Любые запросы к Next.js, содержащие эти куки, будут рассматриваться как режим предварительного просмотра, и поведение для статически сгенерированных страниц изменится (подробнее об этом позже).
Вы можете протестировать это вручную, создав API-маршрут, как показано ниже, и обратившись к нему вручную из браузера:
// Простой пример для ручного тестирования из браузера.
export default function handler(req, res) {
res.setPreviewData({})
res.end('Режим предварительного просмотра включен')
}
Если вы откроете инструменты разработчика в браузере и посетите /api/preview
, вы заметите, что куки __prerender_bypass
и __next_preview_data
будут установлены для этого запроса.
Безопасный доступ из вашей Headless CMS
На практике вы захотите вызывать этот API-маршрут безопасно из вашей headless CMS. Конкретные шаги будут зависеть от используемой headless CMS, но вот некоторые общие действия, которые вы можете предпринять.
Эти шаги предполагают, что ваша headless CMS поддерживает настройку пользовательских URL-адресов предварительного просмотра. Если нет, вы всё равно можете использовать этот метод для защиты URL-адресов предварительного просмотра, но вам нужно будет вручную создавать и обращаться к URL-адресу предварительного просмотра.
Во-первых, создайте секретный токен с помощью генератора токенов. Этот секрет будет известен только вашему приложению Next.js и вашей headless CMS. Это предотвращает доступ к URL-адресам предварительного просмотра для тех, у кого нет доступа к CMS.
Во-вторых, если ваша headless CMS поддерживает настройку пользовательских URL-адресов предварительного просмотра, укажите следующий URL-адрес в качестве адреса предварительного просмотра. Предполагается, что ваш API-маршрут предварительного просмотра находится по адресу pages/api/preview.js
.
https://<your-site>/api/preview?secret=<token>&slug=<path>
<your-site>
должен быть вашим доменом развертывания.<token>
должен быть заменён на сгенерированный секретный токен.<path>
должен быть путём к странице, которую вы хотите просмотреть. Если вы хотите просмотреть/posts/foo
, то следует использовать&slug=/posts/foo
.
Ваша headless CMS может позволить вам включить переменную в URL-адрес предварительного просмотра, чтобы <path>
мог быть установлен динамически на основе данных CMS, например: &slug=/posts/{entry.fields.slug}
Наконец, в API-маршруте предварительного просмотра:
- Проверьте, что секрет совпадает и что параметр
slug
существует (если нет, запрос должен завершиться ошибкой). - Вызовите
res.setPreviewData
. - Затем перенаправьте браузер на путь, указанный в
slug
. (В следующем примере используется 307 редирект).
export default async (req, res) => {
// Проверка секрета и параметров
// Этот секрет должен быть известен только этому API-маршруту и CMS
if (req.query.secret !== 'MY_SECRET_TOKEN' || !req.query.slug) {
return res.status(401).json({ message: 'Неверный токен' })
}
// Запрос к headless CMS для проверки существования указанного `slug`
// getPostBySlug реализует необходимую логику запроса к headless CMS
const post = await getPostBySlug(req.query.slug)
// Если slug не существует, предотвратите включение режима предварительного просмотра
if (!post) {
return res.status(401).json({ message: 'Неверный slug' })
}
// Включение режима предварительного просмотра путем установки кук
res.setPreviewData({})
// Перенаправление на путь из полученного поста
// Мы не перенаправляем на req.query.slug, чтобы избежать уязвимостей открытого перенаправления
res.redirect(post.slug)
}
Если всё прошло успешно, браузер будет перенаправлен на путь, который вы хотите просмотреть, с установленными куками режима предварительного просмотра.
Шаг 2: Обновление getStaticProps
Следующий шаг — обновить getStaticProps
для поддержки режима предварительного просмотра.
Если вы запрашиваете страницу, которая имеет getStaticProps
, с установленными куками режима предварительного просмотра (через res.setPreviewData
), то getStaticProps
будет вызван во время запроса (а не во время сборки).
Кроме того, он будет вызван с объектом context
, где:
context.preview
будетtrue
.context.previewData
будет таким же, как аргумент, переданный вsetPreviewData
.
export async function getStaticProps(context) {
// Если вы запрашиваете эту страницу с установленными куками режима предварительного просмотра:
//
// - context.preview будет true
// - context.previewData будет таким же,
// как аргумент, переданный в `setPreviewData`.
}
Мы использовали res.setPreviewData({})
в API-маршруте предварительного просмотра, поэтому context.previewData
будет {}
. Вы можете использовать это для передачи информации о сеансе из API-маршрута предварительного просмотра в getStaticProps
, если это необходимо.
Если вы также используете getStaticPaths
, то context.params
также будет доступен.
Получение данных предварительного просмотра
Вы можете обновить getStaticProps
для получения разных данных в зависимости от context.preview
и/или context.previewData
.
Например, ваша headless CMS может иметь другой API-эндпоинт для черновиков постов. В этом случае вы можете использовать context.preview
для изменения URL-адреса API-эндпоинта, как показано ниже:
export async function getStaticProps(context) {
// Если context.preview равен true, добавьте "/preview" к API-эндпоинту
// для запроса данных черновика вместо опубликованных данных. Это может отличаться
// в зависимости от используемой headless CMS.
const res = await fetch(`https://.../${context.preview ? 'preview' : ''}`)
// ...
}
Вот и всё! Если вы обращаетесь к API-маршруту предварительного просмотра (с secret
и slug
) из вашей headless CMS или вручную, вы теперь должны видеть контент для предварительного просмотра. И если вы обновите черновик без публикации, вы сможете просмотреть изменения.
Установите это в качестве URL-адреса предварительного просмотра в вашей headless CMS или обращайтесь вручную, и вы сможете видеть предварительный просмотр.
https://<your-site>/api/preview?secret=<token>&slug=<path>
Дополнительные детали
Полезно знать: во время рендеринга
next/router
предоставляет флагisPreview
, см. документацию по объекту router для получения дополнительной информации.
Указание длительности режима предварительного просмотра
setPreviewData
принимает необязательный второй параметр, который должен быть объектом с настройками. Он принимает следующие ключи:
maxAge
: Указывает количество секунд, в течение которых будет длиться сеанс предварительного просмотра.path
: Указывает путь, к которому применяется кука. По умолчанию/
, что включает режим предварительного просмотра для всех путей.
setPreviewData(data, {
maxAge: 60 * 60, // Куки режима предварительного просмотра истекают через 1 час
path: '/about', // Куки режима предварительного просмотра применяются к путям с /about
})
Очистка кук режима предварительного просмотра
По умолчанию для кук режима предварительного просмотра не устанавливается дата истечения, поэтому сеанс предварительного просмотра завершается при закрытии браузера.
Чтобы очистить куки режима предварительного просмотра вручную, создайте API-маршрут, который вызывает clearPreviewData()
:
export default function handler(req, res) {
res.clearPreviewData({})
}
Затем отправьте запрос к /api/clear-preview-mode-cookies
для вызова API-маршрута. Если вы вызываете этот маршрут с помощью next/link
, вы должны передать prefetch={false}
, чтобы предотвратить вызов clearPreviewData
во время предварительной загрузки ссылки.
Если в вызове setPreviewData
был указан путь, вы должны передать тот же путь в clearPreviewData
:
export default function handler(req, res) {
const { path } = req.query
res.clearPreviewData({ path })
}
Ограничения размера previewData
Вы можете передать объект в setPreviewData
, и он будет доступен в getStaticProps
. Однако, поскольку данные будут храниться в куке, есть ограничение на размер. В настоящее время данные предварительного просмотра ограничены 2 КБ.
Работа с getServerSideProps
Режим предварительного просмотра также работает с getServerSideProps
. Он также будет доступен в объекте context
, содержащем preview
и previewData
.
Полезно знать: Вы не должны устанавливать заголовок
Cache-Control
при использовании режима предварительного просмотра, так как его нельзя обойти. Вместо этого мы рекомендуем использовать ISR (инкрементальную статическую регенерацию).
Работа с API-маршрутами
API-маршруты будут иметь доступ к preview
и previewData
в объекте запроса. Например:
export default function myApiRoute(req, res) {
const isPreview = req.preview
const previewData = req.previewData
// ...
}
Уникальность для каждого next build
Как значение куки обхода, так и приватный ключ для шифрования previewData
изменяются при завершении next build
. Это гарантирует, что куки обхода не могут быть угаданы.
Полезно знать: Для тестирования режима предварительного просмотра локально через HTTP ваш браузер должен разрешать сторонние куки и доступ к локальному хранилищу.