Sitemap Generator
The `sitemap` package is a high-level, streaming library and CLI tool designed for generating and managing XML sitemap files according to the sitemap.org protocol. It facilitates the creation of sitemaps and sitemap indexes, supporting various content types like images, videos, and multilingual alternatives. The package is actively maintained, with version 9.0.1 being the current stable release, frequently issuing security patches across major versions (e.g., 7.x, 8.x, 9.x) and introducing significant breaking changes in major releases like v9.0.0. Key differentiators include its robust, security-focused architecture (addressing XML injection, memory DoS, and arbitrary file writes), stream-based processing for efficiency with large datasets, and a command-line interface for quick generation and validation. It offers comprehensive TypeScript support for type safety and IntelliSense.
Common errors
-
XML validation error: Invalid attribute 'xsi:schemaLocation' in XML namespace
cause Older versions of the validator incorrectly rejected namespace-qualified attributes like `xsi:schemaLocation`.fixUpgrade to `sitemap@8.0.2` or newer. This version extended validation to accept such attributes, fixing issue #464. -
Circular dependency breaking Node.js 20.6 / Maximum call stack size exceeded
cause A circular dependency issue, primarily affecting Node.js 20.6, caused stack overflow errors during package initialization.fixUpgrade to `sitemap@7.1.2` or newer, which contains a fix for this specific circular dependency.
Warnings
- breaking Version 9.0.0 dropped support for Node.js versions older than 20.19.5 and npm versions older than 10.8.2. It also transitioned to an ESM-first architecture.
- breaking The package moved to an ESM-first architecture in v9.0.0, utilizing `"type": "module"` in `package.json` and conditional exports. While CommonJS `require` is still supported for most direct imports, direct file imports might require `.js` extensions.
- breaking Sitemap generation typically limits a single sitemap file to 50,000 URLs and 50MB (uncompressed). Exceeding these limits can lead to search engines ignoring parts of your sitemap.
- security Multiple XML injection vulnerabilities (BB-01) were fixed, primarily concerning unescaped `xslUrl` in stylesheet processing instructions. Special characters (`&`, `"`, `<`, `>`) were not properly escaped.
- security Security vulnerabilities (BB-02, BB-03, BB-04, BB-05) related to excessive resource consumption and arbitrary file writes were addressed. These include enforcing 50,000 URL limits in `XMLToSitemapItemStream`, capping parser error arrays to prevent memory DoS, rejecting absolute `destinationDir` paths, and promptly destroying streams when `maxEntries` are exceeded during parsing.
Install
-
npm install sitemap -
yarn add sitemap -
pnpm add sitemap
Imports
- SitemapStream
const { SitemapStream } = require('sitemap')import { SitemapStream } from 'sitemap' - SitemapItem
import SitemapItem from 'sitemap'
import { SitemapItem } from 'sitemap' - streamToPromise
import { streamToPromise } from 'sitemap/lib/streamToPromise'import { SitemapStream, streamToPromise } from 'sitemap' - simpleSitemapAndIndex
const simpleSitemapAndIndex = require('sitemap').simpleSitemapAndIndeximport { simpleSitemapAndIndex } from 'sitemap'
Quickstart
import { SitemapStream, streamToPromise, SitemapItem } from 'sitemap';
import { createGzip } from 'node:zlib';
import { Readable } from 'node:stream';
import { writeFile } from 'node:fs/promises';
const hostname = process.env.SITE_HOSTNAME ?? 'https://example.com';
const links: SitemapItem[] = [
{ url: '/', changefreq: 'daily', priority: 1.0 },
{ url: '/about', changefreq: 'monthly', priority: 0.7 },
{ url: '/contact', changefreq: 'weekly', priority: 0.5, lastmod: new Date() },
{
url: '/products/widget',
lastmod: '2023-11-20',
img: [
{ url: `${hostname}/img/widget.jpg`, caption: 'Awesome Widget' },
],
},
{ url: '/blog/post-1', changefreq: 'weekly' },
{ url: '/blog/post-2', lastmod: '2024-01-15', priority: 0.8 },
];
(async () => {
try {
const sitemapStream = new SitemapStream({ hostname });
const pipeline = Readable.from(links).pipe(sitemapStream).pipe(createGzip());
const sitemapXml = await streamToPromise(pipeline);
await writeFile('./public/sitemap.xml.gz', sitemapXml);
console.log('Sitemap generated successfully to public/sitemap.xml.gz');
} catch (error) {
console.error('Error generating sitemap:', error);
}
})();