Генерация статических сайтов (SSG)
Примеры
- Пример с WordPress(Демо)
- Блог на markdown (Демо)
- Пример с DatoCMS (Демо)
- Пример с TakeShape (Демо)
- Пример с Sanity (Демо)
- Пример с Prismic (Демо)
- Пример с Contentful (Демо)
- Пример с Strapi (Демо)
- Пример с Prepr (Демо)
- Пример с Agility CMS (Демо)
- Пример с Cosmic (Демо)
- Пример с ButterCMS (Демо)
- Пример с Storyblok (Демо)
- Пример с GraphCMS (Демо)
- Пример с Kontent (Демо)
- Пример с Builder.io (Демо)
- Пример с TinaCMS (Демо)
- Static Tweet (Демо)
- Пример с Enterspeed (Демо)
Если страница использует генерацию статических сайтов (SSG), её HTML генерируется во время сборки. Это означает, что в production HTML страницы создаётся при выполнении команды next build
. Затем этот HTML будет повторно использоваться при каждом запросе и может кэшироваться CDN.
В Next.js вы можете генерировать страницы статически с данными или без них. Рассмотрим оба случая.
Статическая генерация без данных
По умолчанию Next.js предварительно рендерит страницы с помощью статической генерации без получения данных. Пример:
function About() {
return <div>О нас</div>
}
export default About
Обратите внимание, что этой странице не нужно получать внешние данные для предварительного рендеринга. В таких случаях Next.js генерирует один HTML-файл для каждой страницы во время сборки.
Статическая генерация с данными
Некоторые страницы требуют получения внешних данных для предварительного рендеринга. Есть два сценария, и один или оба могут применяться. В каждом случае вы можете использовать предоставляемые Next.js функции:
- Содержимое вашей страницы зависит от внешних данных: используйте
getStaticProps
. - Пути (paths) вашей страницы зависят от внешних данных: используйте
getStaticPaths
(обычно вместе сgetStaticProps
).
Сценарий 1: Содержимое страницы зависит от внешних данных
Пример: ваша страница блога может нуждаться в получении списка постов из CMS (системы управления контентом).
// TODO: Нужно получить `posts` (вызвав API)
// перед предварительным рендерингом страницы.
export default function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}
Для получения этих данных при предварительном рендеринге Next.js позволяет экспортировать async
функцию getStaticProps
из того же файла. Эта функция вызывается во время сборки и позволяет передать полученные данные в props
страницы при предварительном рендеринге.
export default function Blog({ posts }) {
// Рендеринг постов...
}
// Эта функция вызывается во время сборки
export async function getStaticProps() {
// Вызов API для получения постов
const res = await fetch('https://.../posts')
const posts = await res.json()
// Возвращая { props: { posts } }, компонент Blog
// получит `posts` как пропс во время сборки
return {
props: {
posts,
},
}
}
Чтобы узнать больше о работе getStaticProps
, изучите документацию по получению данных.
Сценарий 2: Пути страницы зависят от внешних данных
Next.js позволяет создавать страницы с динамическими маршрутами. Например, вы можете создать файл pages/posts/[id].js
для отображения отдельного поста блога по id
. Это позволит показывать пост с id: 1
при переходе на posts/1
.
Подробнее о динамической маршрутизации в документации.
Однако, какие id
нужно предварительно рендерить во время сборки, может зависеть от внешних данных.
Пример: предположим, вы добавили в базу данных только один пост (с id: 1
). В этом случае вам нужно предварительно рендерить только posts/1
.
Позже вы можете добавить второй пост с id: 2
. Тогда нужно будет предварительно рендерить и posts/2
.
Таким образом, пути предварительно рендерящихся страниц зависят от внешних данных. Для этого Next.js позволяет экспортировать async
функцию getStaticPaths
из динамической страницы (в данном случае pages/posts/[id].js
). Эта функция вызывается во время сборки и позволяет указать, какие пути нужно предварительно рендерить.
// Эта функция вызывается во время сборки
export async function getStaticPaths() {
// Вызов API для получения постов
const res = await fetch('https://.../posts')
const posts = await res.json()
// Получаем пути для предварительного рендеринга на основе постов
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// Предварительно рендерим только эти пути.
// { fallback: false } означает, что другие маршруты вернут 404.
return { paths, fallback: false }
}
Также в pages/posts/[id].js
нужно экспортировать getStaticProps
, чтобы получить данные о посте по id
и использовать их для предварительного рендеринга страницы:
export default function Post({ post }) {
// Рендеринг поста...
}
export async function getStaticPaths() {
// ...
}
// Эта функция также вызывается во время сборки
export async function getStaticProps({ params }) {
// params содержит `id` поста.
// Если маршрут /posts/1, то params.id будет 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Передаём данные поста в страницу через props
return { props: { post } }
}
Чтобы узнать больше о работе getStaticPaths
, изучите документацию по получению данных.
Когда использовать статическую генерацию?
Мы рекомендуем использовать статическую генерацию (с данными и без) везде, где это возможно, потому что ваша страница может быть собрана один раз и обслуживаться через CDN, что делает её намного быстрее, чем рендеринг на сервере при каждом запросе.
Статическую генерацию можно использовать для многих типов страниц, включая:
- Маркетинговые страницы
- Посты блога и портфолио
- Списки товаров интернет-магазинов
- Справка и документация
Задайте себе вопрос: "Можно ли предварительно отрендерить эту страницу до запроса пользователя?" Если ответ "да", выбирайте статическую генерацию.
С другой стороны, статическая генерация не подходит, если вы не можете предварительно отрендерить страницу до запроса пользователя. Например, если страница показывает часто обновляемые данные, и её содержимое меняется при каждом запросе.
В таких случаях можно:
- Использовать статическую генерацию с получением данных на стороне клиента: можно пропустить предварительный рендеринг некоторых частей страницы и заполнить их с помощью JavaScript на стороне клиента. Подробнее в документации по получению данных.
- Использовать рендеринг на стороне сервера (SSR): Next.js будет предварительно рендерить страницу при каждом запросе. Это медленнее, так как страница не может кэшироваться CDN, но предварительно отрендеренная страница всегда будет актуальной. Мы рассмотрим этот подход далее.
Рендеринг на стороне сервера (SSR)
Используйте рендеринг на стороне сервера (Server-side Rendering) для генерации HTML при каждом запросе.
Автоматическая статическая оптимизация
Next.js автоматически оптимизирует ваше приложение для генерации статического HTML, когда это возможно. Узнайте, как это работает.