Next.js Sitemap: автоматическое добавление динамических URL-адресов в nextjs 13 app router sitemap.js

Карта сайта является важным аспектом любого веб-сайта, поскольку она помогает поисковым системам обнаруживать и индексировать все страницы на сайте. Для веб-сайтов Next.js создание динамического файла sitemap.js — это эффективный способ гарантировать, что все динамические URL-адреса, такие как сообщения в блогах, и нединамические URL-адреса, такие как страницы, добавленные вручную, будут включены в карту сайта. В этом сообщении блога мы рассмотрим процесс создания обширного и тщательного АВТОМАТИЧЕСКОГО файла sitemap.js для веб-сайта Next.js, который включает как статические URL-адреса, так и динамические страницы, такие как, например, сообщения в блогах.

Статические URL-адреса

Получение всех статических веб-страниц внутри каталога приложений вашего веб-сайта Nextjs (или каталога страниц для ленивых разработчиков, которые еще не обновились).

Внутри вашего файла sitemap.js, который для тех, кто не знает, должен находиться в каталоге вашего приложения — если вы все еще используете старый способ страниц — обновитесь, но для вас, крутых детей, использующих новый маршрутизатор приложений, либо добавьте ниже в существующий файл sitemap.(js/ts) или создайте его с указанным ниже.

const fs = require('fs');
const path = require('path');

function getFoldersRecursive(filePath) {
  const folders = [];

  function shouldIgnoreFolder(folderName) {
    const ignoredPrefixes = ['[', '(', '_', '-'];
    return ignoredPrefixes.some((prefix) => folderName.startsWith(prefix));
  }

  function traverse(currentPath) {
    const files = fs.readdirSync(currentPath, { withFileTypes: true });

    files.forEach((file) => {
      if (file.isDirectory()) {
        const folderName = file.name;
        if (!shouldIgnoreFolder(folderName)) {
          folders.push(folderName);
          traverse(path.join(currentPath, folderName));
        }
      }
    });
  }

  traverse(filePath);
  return folders;
}

// Usage example
const targetPath = '/path/to/your/folder';
const folderNames = getFoldersRecursive(targetPath);
console.log(folderNames);

Этот небольшой фрагмент будет рекурсивно искать любой путь к файлу, который вы ему укажете, поэтому для нас, используя маршрутизатор приложения, вы получите что-то вроде:

const staticPages = getFoldersRecursive("/src/app")

или для людей, не использующих каталог src:

const staticPages = getFoldersRecursive("/app")

Сценарий вернет все жестко закодированные URL-адреса страниц, которые вы сделали для таких страниц, как «О нас», «Контакты», «Услуги», вы знаете, страницы, которые вы всегда жестко задаете. Он также будет игнорировать любые папки, которые являются шаблоном динамического URL-адреса, поэтому все, что начинается с «[», «(», «-» или «_».

Динамические URL-адреса

Получите все заголовки динамически созданных страниц, таких как сообщения в блогах, учебные пособия и любые другие динамические страницы, которых нет в каталоге вашего приложения, но есть папки, такие как «[slug]» или «[post]». Это немного сложнее, так как это зависит от вашего конкретного API, но мой API-интерфейс django rest framework, который я написал, я всегда включаю поиск слагов, чтобы я мог включить слаг сообщений в список сообщений json, так что что-то вроде этого:

"http://localhost:8000/api/posts/all/"

Что возвращает:

[
  {
    ...
    "title" : "Post 1",
    "slug": "post-1",
    ...
  },
  {
    ...
    "title" : "Post 2",
    "slug": "post-2",
    ...
  },
  {
    ...
    "title" : "Post 3",
    "slug": "post-3",
    ...
  }
]

Итак, теперь, помимо API, который отлично подходит для заполнения страницы со списком блогов, я также могу использовать эту конечную точку для заполнения моей карты сайта всеми слагами! Вот точный код, который я использую для этого:

interface Post {
  slug: string;
  updated_at: string;
}
const createJson=(post: Post) => {
  return {
    url: `https://website.com/posts/${post.slug}`,
    lastModified: new Date(post.updated_at), // Replace 'updated_at' with the actual field name containing the last modified date for the post
  }
}

async function getAllPostSlugs() {
  try {
    const response = await axios.get('https://api.website.com/api/posts/');
    const posts = response.data;
    return posts.map((post:Post) => createJson(post));
  } catch (error: any) {
    console.error('Error fetching posts:', error.message);
    return [];
  }
}