
Алексей Баранов
Добавляем пагинацию в статический блог на Next.js
Продолжаю работать над улучшением блога и одновременно разбираться в Next.js. В этой статье расскажу как добавить пагинацию к статическим страницам блога.
Процесс можно разделить на несколько этапов:
- Разделение логики страницы на динамическую и статическую
- Добавление навигационного компонента
- Работа над поисковой выдачей
Результат можно посмотреть в самом низу страницы с постами.
Разделение логики страницы на динамическую и статическую
Мне не хотелось менять структуру страниц сайта, поэтому я решил что страницу буду прокидывать через query string.
Статические страницы в Next.js имеют ряд ограничений при работе с query string. По сути, единственный доступный в моём случае способ получить доступ к параметрам из URL - воспользоваться хуком useSearchParams из клиентского компонента.
Для этого необходимо вынести получение данных о постах в код статической страницы, и передать их в клиентский компонент, который сможет отфильтровать их нужным нам способом и отрисовать нужный нам список постов.
import { Suspense } from "react";
export default function PostsPage() {
const posts = getAllPostsMeta();
const tags = getAllTags();
return (
<>
// ...
<Suspense fallback={<StaticPosts posts={posts} tags={tags} />}>
<DynamicPosts posts={posts} tags={tags} />
</Suspense>
// ...
</>
);
}
Заметьте что компонент DynamicPosts обёрнут в Suspense. Фоллбек будет отрендерен в build-time. А компонент DynamicPosts будет отрендерен уже во время исполнения кода страницы на клиенте.
"use client"
// ...
const DynamicPage: React.FC<Props> = ({ posts, tags }) => {
const searchParams = useSearchParams();
const page = Number(searchParams.get("page")) || 1;
const maxPage = Math.ceil(posts.length / POSTS_PER_PAGE);
const pageOffset = (page - 1) * POSTS_PER_PAGE;
const pagePosts = posts.slice(pageOffset, pageOffset + POSTS_PER_PAGE);
if (!pagePosts.length) return notFound();
return (
<>
<Posts posts={pagePosts} title={"Посты"} withFilter tags={tags} />
<PageSelector page={page} maxPage={maxPage} />
</>
);
};
Добавление навигационного компонента
Для навигационного компонента, будем использовать компонент Link из встроенного пакета next/link и прокидывать в параметр href необходимую нам страницу.
<Link href={`./?page=${page}`}>{page}</Link>
Сильно углубляться в подробности реализации не буду, скажу лишь что в результате получилось вот так:
Навигационный компонент
Работа над поисковой выдачей
Для того чтобы не получить дублирующиеся страницы в поиске, и не усложнить себе жизнь долгим процессом удалением дублей, необходимо сделать следующее:
Добавление ссылки на каноническую страницу
Для того чтобы правильно пройти через процесс нормализации, необходимо добавить ссылку на каноническую страницу.
<link rel="canonical" href="https://alexeybaranov.dev/posts" />
В Next.js есть специальное Metadata API, которое можно использовать как раз для этих целей.
Воспользуемся им:
export const metadata: Metadata = {
title: "Посты | Алексей Баранов. Блог",
description: "Страница со всеми опубликованными постами",
alternates: {
canonical: `/posts`,
},
};
Добавление директивы Clean-Param в robots.txt
Яндекс поддерживает специальную директиву Clean-param в файлах robots.txt.
Давайте добавим её:
User-agent: Yandex
Clean-param: page
Allow: /
На этом всё! 🎉
Подписывайтесь на мой Youtube канал, Telegram и на сообщество Вконтакте 🙂



