Алексей Баранов

Обо мне

Cover Image for Добавляем поиск по тегам в статический блог на Next.js

Добавляем поиск по тегам в статический блог на Next.js

Несмотря на то, что я немного сбавил обороты, количество постов в блоге понемногу прибавляется, а находить их становится сложнее, поэтому я решил добавить поиск постов по тегам.

Вот так он выглядит на момент написания этой статьи:

Результат

Процесс можно разделить на несколько этапов:

Добавление тегов к постам

Тут всё просто, как и в случае с рекомендациями, я решил захардкодить в frontmatter каждой статьи массив с тегами.

Например, для этой статьи массив выглядит следующим образом:

tags: ["улучшения блога", "nextjs"]

Если вы пойдёте этим же путём, то обратите внимание на то, что в названии тегов лучше не использовать кириллицу и спец. символы. О том как всё же использовать в тегах кириллицу читайте далее в статье.

Генерация страниц для каждого тега

Генерация страниц для тегов очень похожа на генерацию страниц постов.

Алгоритм очень простой и выглядит следующим образом:

Сбор уникальных тегов

О том как получить все посты и их метаданные я писал в статье о добавлении RSS фида.

Там же можно найти и полную реализацию метода getAllPosts.

А нам же остаётся только добавить все теги в массив и удалить оттуда дубли:

export function getAllTags(): string[] {
  const notUniqueTags = getAllPosts().flatMap((p) =>
    p.tags ? [...p.tags] : [],
  );

  return Array.from(new Set(notUniqueTags));
}

Генерация страниц

Для того чтобы сгенерировать страницы, нам нужен не только список тегов, но и список постов по тегу:

export function getAllPostsByTag(tag: string): Post[] {
  return getAllPosts().filter((p) => p.tags?.includes(tag));
}

Далее добавляем компонент для отображения страницы:

type Params = {
  params: {
    tag: string;
  };
};

// Компонент для отображения страницы
export default async function TagPage({ params }: Params) {
  const decodedTag = getTagFromURI(params.tag);

  const posts = getAllPostsByTag(decodedTag);

  if (!posts.length) {
    return notFound();
  }

  return (
    <>
      // Отображаем тут наши посты
    </>
  );
}

И генерируем статические страницы:

// Генерируем статические страницы в build-time
export async function generateStaticParams() {
  const tags = getAllTags();

  return tags.map((t) => ({
    tag: getTagURI(t),
  }));
}

Неочевидные моменты

Вы наверняка заметили что я использую функции getTagFromURI и getTagURI при работе с тегами.

Дело в том что на данный момент в Next.js существуют сложности с кириллическими путями.

export const getTagURI = (tag: string) => {
  return process.env.NODE_ENV === "development" ? encodeURIComponent(tag) : tag;
};

export const getTagFromURI = (uri: string) => {
  return decodeURIComponent(uri);
};

Тут сказать особо нечего, единственный момент, который следует учитывать - не забывайте оборачивать теги в encodeURIComponent.

const TagLinks: React.FC = () => {
  const tags = getAllTags();

  return (
    <div>
      {tags.map((item, i) => (
        <Link
          href={`/tags/${getTagURI(item)}`}
          key={i}
        >
          {`#${item}`}
        </Link>
      ))}
    </div>
  );
};

Работа над поисковой выдачей

Для улучшения индексирования сгенерированные страницы можно добавить в файл sitemap сайта.

Для этого, в файл sitemap.ts, лежащий в корне сайта добавляем следующий код:

import { MetadataRoute } from "next";

import { getAllTags, getTagURI } from "@/lib/api";

export default function sitemap(): MetadataRoute.Sitemap {
  const tags = getAllTags();
  return [
    // тут остальные страницы сайта
    ...tags.map((tag) => ({
      url: `https://alexeybaranov.dev/tags/${getTagURI(tag)}`,
      lastModified: new Date(),
      priority: 0.7,
    })),
  ];
}

На этом всё! 🎉

Подписывайтесь на мой Youtube канал, Telegram и на сообщество Вконтакте 🙂

В живую результат статьи можно увидеть ниже 🙂

Поделиться

Вам может быть интересно:

Cover Image for Добавляем рекомендации постов и блок "Поделиться в соц. сетях"

Добавляем рекомендации постов и блок "Поделиться в соц. сетях"

Изучал различные блоги, аналогичные моему и решил добавить блок "Поделиться в соц. сетях", а так же простейший механизм рекомендаций статей. Вот что из этого вышло...

Cover Image for Добавляем RSS-фид к статическому Next.js приложению

Добавляем RSS-фид к статическому Next.js приложению

Сам я не пользуюсь RSS фидами, но так как формат ещё жив, решил добавить фид и для этого блога...