Crea un sitemap dinámico con Node.js y TypeScript

Crea un sitemap dinámico con Node.js y TypeScript

Cada vez que realizo un proyecto siempre es necesario crear archivos sitemap.xml, el cual me permite indicarle a google que paginas debe indexar en su motor de busqueda. Y es beneficioso para darle mayor visibilidad al proyecto en internet.

En esta ocasion creare un archivo sitemap.ts, no necesariamente debe ser con typescript pero es una preferencia personal.

Necesitamos tener todas las rutas que tengamos en nuestro proyecto. y nuestro dominio principal y cuantos sitemaps vamos a generar.

type ChangeFreqType = 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
type PriorityType=  0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1.0;
type PathsProps ={
    path:string
    changefreq?: ChangeFreqType;
    priority?:PriorityType;
}

const data:PathsProps[] = [
    { path: '/pagina-1' },
    { path: '/pagina-2' },
    { path: '/pagina-3' },
    { path: '/pagina-4' },
    { path: '/pagina-5' }
]

const ENDPOINT_URL = "https://example.com";
const QUANTITY = 1;

El siguiente paso es dividir en cuantos archivos sitemap vamos a dividir nuestras rutas. en este caso yo solamente quiero 1 debido a que son pocas rutas. pero dependiendo de la cantidad debes considerar aumentar la cantidad. Debido a que los sitemaps no deben superar las 50,000 registros. si deseas mas informacion consulta la pagina de google.

Luego de dividir nuestras rutas tambien tenemos opciones generales como que changefreq y priority tendran nuestras urls. en este caso yo deseo que todas mis urls tengan changefreq "daily" y priority de 0.5.

y por ultimo necesitamos crear un sitemap.xml el cual debe contener todas las demas rutas pero de los sitemaps generados anteriormente.


function splitArrayIntoParts<T>(array: T[], parts: number) {
  const partSize = Math.ceil(array.length / parts);
  return Array.from({ length: parts }, (_, index) =>
    array.slice(index * partSize, (index + 1) * partSize)
  );
}

type Options = {
  changefreq: ChangeFreqType;
  priority: PriorityType;
};

function createSitemaps(
  paths: PathsProps[],
  quantity: number,
  props?: Options
) {
  const sitemaps = splitArrayIntoParts(paths, quantity);

  const { changefreq = "daily", priority = 0.5 } = props ?? {};

  const lastmod = new Date().toISOString();

  const START_SITEMAP_URLSET = `<?xml version="1.0" encoding="UTF-8"?>
   <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`;

  const END_SITEMAP_URLSET = `
   </urlset>`;

  const xmls = sitemaps?.map((data) => {
    const urlset: string = data
      .map((value) => {
        return `<url>
               <loc>${ENDPOINT_URL}${value.path}</loc>
               <lastmod>${lastmod}</lastmod>
               <changefreq>${changefreq ?? value?.changefreq}</changefreq>
              <priority>${priority ?? value?.priority}</priority>
           </url>`;
      })
      .join("");

    return START_SITEMAP_URLSET + urlset + END_SITEMAP_URLSET;
  });

  return xmls;
}

const createMainSitemap = (nSitemaps: number) => {
  const START_SITEMAP_INDEX = `<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`;

  const END_SITEMAP_INDEX = `
</sitemapindex>`;
  const urlset = Array.from({ length: nSitemaps }, (_, index) => index)
    .map((index) => {
      return `<sitemap>
  <loc>${ENDPOINT_URL}/sitemap-${index}.xml</loc>
</sitemap>`;
    })
    .join("");
  return START_SITEMAP_INDEX + urlset + END_SITEMAP_INDEX;
};

Por ultimo tenemos que guardar los sitemaps generados como archivos xml, en este caso utilizare la API de Nodejs.

Debemos proporcionar el filename que debe terminar en extension .xml y el contenido. y lo guardare en la carpeta public del proyecto

import fs from "fs";
import { join } from "path";

const saveAsXML = (filename: string, xml: string) => {
  const path = join(process.cwd(), "public", filename);
  fs.writeFile(path, xml, (err) => {
    if (err) {
      console.error(`Error al escribir el archivo ${filename}:`, err);
    } else {
      console.log(`${filename} creado exitosamente.`);
    }
  });
};

Por ultimo debemos guardarlos y ejecutar el comando:

pnpm tsx sitemap.ts
const sitemaps = createSitemaps(data, QUANTITY, {
  changefreq: "daily",
  priority: 0.5,
});

const sitemap = createMainSitemap(QUANTITY);

saveAsXML("sitemap.xml", sitemap);

for (let index = 0; index < sitemaps.length; index++) {
  const data = sitemaps[index];
  saveAsXML(`sitemap-${index}.xml`, data);
}

Y para valdiar si estan correctamente debemos utilice esta pagina. o un validador de sitemap

¡Si te gustó este artículo, suscríbete para recibir actualizaciones y compártelo con tus amigos y colegas! Tu apoyo es muy valioso y contribuye a que más personas descubran mi contenido. ¡Gracias!