ekalinin/sitemap.js

index with multiple categorized sitemaps

tasiotas opened this issue · 5 comments

Hi,

I would like to split sitemaps per category and have them all referenced in sitemap-index.xml.
It does not seem to be trivial given existing examples. Does anyone have done similar setup?

This is what I would like to achieve, currently I can only write to single sitemap stream. Following SitemapAndIndexStream example.

<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <sitemap>
    <loc>https://website.com/sitemap-blog-0.xml</loc>
  </sitemap>
  <sitemap>
    <loc>https://website.com/sitemap-blog-1.xml</loc>
  </sitemap>
  <sitemap>
    <loc>https://website.com/sitemap-shop-0.xml</loc>
  </sitemap>
  <sitemap>
    <loc>https://website.com/sitemap-shop-1.xml</loc>
  </sitemap>
</sitemapindex>

perhaps its out of scope of this project. I managed to split it with simpleSitemapAndIndex and lots of additional code

@tasiotas Can you please show me how did you manage to create different multiple sitemaps with indexing.

sorry, in the end I dropped sitemap.js lib and went full with custom code writing my own XMLs.

I dont have a code at hand where I had it working with simpleSitemapAndIndex. I believe I was calling it multiple times, and then moving/renaming output file. I had to generate indexes by hand anyway...

@tasiotas Thanks for the quick response.
Even I considered doing custom code to generate XML as I want as the package is less supportive for creating multiple sitemaps at once and index it in sitemap.xml.

It's a little late to be here but here is how I managed it.

import fs from "node:fs";
import { type SitemapItemLoose, SitemapAndIndexStream, SitemapStream, SitemapIndexStream } from "sitemap";

const hostname = "https://...";

export default class SitemapApplication {

    generateSitemap() {
        const blogs= []; /* get items from somewhere */
        const books= []; /* get items from somewhere */
        const movies= []; /* get items from somewhere */

        this.createSitemapCategory(blogs, "blog", true);
        this.createSitemapCategory(books, "books", true);
        this.createSitemapCategory(movies, "movies", true);

        this.createIndexStream(["blog", "books", "movies"]);
    }

    private createIndexStream(categories: string[]) {
        const indexStream = new SitemapIndexStream();
        categories.forEach(category => indexStream.write({ url: `${hostname}/sitemap_${category}.xml` }));
        indexStream.pipe(fs.createWriteStream("sitemap_index.xml"));
        indexStream.end();
    }

    private createSitemapCategory(data: SitemapItemLoose[], name: string, singleFile = false) {
        const stream = new SitemapAndIndexStream({
            getSitemapStream: index => {
                const sitemapStream = new SitemapStream({
                    hostname: hostname
                });
                const filePath = singleFile && index === 0 ? `sitemap_${name}.xml` : `sitemap_${name}-${index}.xml`;

                const ws = sitemapStream
                    .pipe(fs.createWriteStream(filePath));

                return [new URL(filePath, hostname).toString(), sitemapStream, ws];
            }
        });

        data.forEach(item => stream.write(item));

        stream.end();
    }
}