Pull to refresh

Comments 6

Переход на Next.js 15 позволил

Судя по статье, это не Next позволил, а разные решения типа кэширования в Redis, которые были вынуждены искать после перехода.

Не совсем.

Мы смогли реализовать много крутых решений благодаря возможностям Next.js и его отличной совместимости с Vercel, особенно с Edge Functions. Это дало нам кучу гибкости и помогло выжать максимум из технологий.

UPD: Также Next.js 15 предоставляет гибридный SSR/ISR/SSG, мощное кеширование через CDN и Redis, отличную поддержку TypeScript, а его интеграция с Gravity UI позволила адаптировать UI под серверный рендеринг. Всё это сделало его идеальным выбором для Hikasami.

Например чистый React:
1. Отсутствие SSR
2. Нет встроенного кеширования

Или возьмем тот же VueJS:
1. ISR не реализован. Он реализован только в NuxtJS (Но наша команда никогда не писала на NuxtJS и вряд ли когда то будет)
2. У Vue довольно слабая экосистема. (Vercel, Cloudflare)

Спасибо за статью, есть вопрос интересный по нексту: как вы делаете и делаете ли вы вообще карту сайта для поисковиков. Сам пытался на нексте это сделать, но закопался. Хотелось бы как-то удобно генерировать все артиклы без заморочек.

Спасибо за вопрос! В Next.js 15 генерация sitemap.xml может быть сложной, особенно если у вас есть динамические страницы, создаваемые по query‑параметрам. Однако, есть несколько способов это реализовать:

1️⃣ Разделение на статические и динамические страницы

  • Статические страницы (/about, /contact, /privacy) можно вручную добавить в sitemap.

2️⃣ Использование generateStaticParams (если маршруты известны заранее)

Если у вас есть предсказуемые динамические маршруты (/blog/[slug]), можно автоматически получить их во время билда:

export async function generateStaticParams() {
  return [{ slug: 'article-1' }, { slug: 'article-2' }];
}

Это отлично работает для предварительно известных маршрутов, но не поможет с query‑параметрами.

3️⃣ Генерация sitemap без БД и API (автоматическое сканирование файлов)

Если маршруты заранее неизвестны, можно автоматически сканировать папку app/, чтобы получить все страницы:

app/sitemap/route.ts

import { NextResponse } from 'next/server';
import fs from 'fs';
import path from 'path';

const SITE_URL = 'https://hikasami.ru';

/**
 * Автоматически получает все маршруты из папки `app/`
 */
function getRoutes(dir: string, prefix = ''): string[] {
  let routes: string[] = [];
  for (const file of fs.readdirSync(dir)) {
    const fullPath = path.join(dir, file);
    if (fs.statSync(fullPath).isDirectory()) {
      if (file.startsWith('[')) {
        routes.push(`${prefix}/${file.replace(/\[|\]/g, '')}`);
      }
      routes = [...routes, ...getRoutes(fullPath, `${prefix}/${file}`)];
    }
  }
  return routes;
}

export async function GET() {
  const staticPaths = ['/', '/about', '/contact'];
  const dynamicRoutes = getRoutes(path.join(process.cwd(), 'app'));
  const allPaths = [...staticPaths, ...dynamicRoutes].map((route) => `${SITE_URL}${route}`);

  return new NextResponse(
    `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      ${allPaths.map((url) => `<url><loc>${url}</loc><lastmod>${new Date().toISOString()}</lastmod></url>`).join('')}
    </urlset>`,
    { headers: { 'Content-Type': 'application/xml' } }
  );
}

4️⃣ Получение sitemap через API (если маршруты хранятся в базе данных)

Если страницы создаются динамически по API, можно получать их так:

📌 app/sitemap/route.ts (получение через API)

import { NextResponse } from 'next/server';

const SITE_URL = 'https://hikasami.ru';

async function fetchRoutesFromAPI() {
  const res = await fetch(`${SITE_URL}/api/articles`);
  if (!res.ok) return [];
  const articles = await res.json();
  return articles.map((article: { slug: string }) => `/blog/${article.slug}`);
}

export async function GET() {
  const staticPaths = ['/', '/about', '/contact'];
  const dynamicRoutes = await fetchRoutesFromAPI();
  const allPaths = [...staticPaths, ...dynamicRoutes].map((route) => `${SITE_URL}${route}`);

  return new NextResponse(
    `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      ${allPaths.map((url) => `<url><loc>${url}</loc><lastmod>${new Date().toISOString()}</lastmod></url>`).join('')}
    </urlset>`,
    { headers: { 'Content-Type': 'application/xml' } }
  );
}


В чем разница?

  • generateStaticParams работает только для известных на этапе билда маршрутов (используется в page.tsx).

  • Сканирование файловой системы (как в коде выше) автоматически добавляет страницы без запроса к БД.

  • Запрос к API → позволяет обновлять sitemap динамически для контента из базы данных.

Итог

  • Статические страницы → добавляем вручную.

  • Динамические страницы с slug → используем generateStaticParams.

  • Динамические страницы с API → запрашиваем маршруты через fetch.

P.S. Надеюсь, все правильно расписал, только что вернулся домой. Если что-то упустил — буду рад обсудить!

Sign up to leave a comment.