Max Schmitt

June 1 2020

How to generate a sitemap.xml with Node.js the simple way

Today I added a sitemap.xml to my website. An XML-sitemap is a really straight-forward way to inform search engines about the pages on your site that should be crawled.

For my site the XML sitemap looks something like this:

XML

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://maxschmitt.me/</loc>
<lastmod>2020-06-01</lastmod>
<changefreq>daily</changefreq>
<priority>1</priority>
</url>
<url>
<loc>https://maxschmitt.me/posts</loc>
<lastmod>2020-06-01</lastmod>
<changefreq>daily</changefreq>
<priority>1</priority>
</url>
<url>
<loc>https://maxschmitt.me/posts/github-actions-ssh-key</loc>
<lastmod>2020-05-17</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://maxschmitt.me/posts/error-reporting-rollbar-nextjs</loc>
<lastmod>2020-01-10</lastmod>
<changefreq>monthly</changefreq>
<priority>0.5</priority>
</url>
<!-- ... -->
</urlset>

There are many methods and npm packages (as you can imagine) for creating XML files and even sitemap.xml files specifically.

For me, everything clicked when I found the xml package on npm.

It has a brilliantly simple API for constructing XML strings from simple JSON objects.

Here is a simplified version of the SitemapWriter class that I wrote for my custom static site generator, using the xml package:

JS

const fs = require('fs-extra')
const xml = require('xml')
class SitemapWriter {
constructor({ outFile, host }) {
this.outFile = outFile
}
async writeSitemap(pages) {
// Construct the XML object
const xmlObject = {
urlset: [
// <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{
_attr: {
xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9',
},
},
// For every page of the site, generate a <url> object
...pages.map((page) => {
return {
// <url>
url: [
// <loc>http://www.example.com/</loc>
{ loc: page.href },
// <lastmod>2005-01-01</lastmod>
{ lastmod: page.srcFileLastModifiedAt },
// <changefreq>monthly</changefreq>
{ changefreq: 'monthly' },
// <priority>0.8</priority>
{ priority: 0.5 },
],
}
}),
],
}
// Generate the XML markup
const xmlString = xml(xmlObject)
// Write the file to disk
await fs.writeFile(this.outFile, '<?xml version="1.0" encoding="UTF-8"?>' + xmlString)
}
}

To see a list of all possible tags and values for sitemap.xml, check out the official protocol documentation.

The xml package is well-established with over 800k weekly downloads, it's written in plain JS, comes with no external dependencies, supports CDATA and even has an optional streaming API.

Have fun building your own sitemap.xml!

P.S.: You might also be interested in my article about building an RSS feed with Node.js.