Generate a sitemap for your static NextJS website, hosted on Netlify
If you’ve read my story on using NextJS as a static site on Netlify, you’ve come across the generating of pages as exportPathMap in the next.config.js
file. I’ve decided to take that functionality one step further by using that list as input to generate a sitemap.xml
file for better SEO performance.
I’ve created a script that reads the list of pages and generates the sitemap standard as an XML file and directly write it to the /static folder. (That last bit ties neatly in with the copying of the _redirects
file from my previous article). The script is available in this gist, and I’ll explain the setup here.
I start by reading the exportPathMap from the next.config.js file. It is exposed after all:
const { exportPathMap } = require('./next.config');
I then map over the object that is provided and basically generate an XML node as entry for every item in the object:
const xmlUrlNode = (domain, pageUrl, lastmod) => {
const url = `${pageUrl}${pageUrl === '/' ? '' : '/'}`;
const loc = `${domain}${url}`;
const priority = getPriority(url); return `<url>
<loc>${loc}</loc>
<lastmod>${lastmod}</lastmod>
<priority>${priority}</priority>
</url>`;
};const sitemap = `${xmlUrlWrapper(
pages.map(page => xmlUrlNode(domain, page, lastModified)).join(`
`) // Join with a newline
)}`;
There’s some stuff going on for formatting the right date, URL etc. That’s pretty straightforward. I decided to base the priority on the levels of the URL path, so I use a short function to subtract .10 for every level. This seems to, more or less, match how online generators interpret my website. So I’m pretty pleased with it so far:
// Pass in a url (home is "/", and gets 1.00, every subsequent level gets 0.10 subtracted)
const getPriority = url => ((100 - (url.split('/').length - 2) * 10) / 100).toFixed(2);
I then proceed to write the generated XML to the a folder that is publicly accessible after deployment on Netlify:
// writeLocation is passed and matches './out/static/' by my defaultfs.writeFile(`${writeLocation}`, sitemap, err => {
if (err) throw err; console.log(`sitemap.xml with ${pages.length} entries was written to ${targetFolder}${fileName}`);
});
Bear in mind that you need to have added some sort of post build script to your process. My package.json
has a postexport script, which I trigger from my Netlify build command:
// ...abbreviated
"scripts": {
"production": "NODE_ENV=production && npm run build",
"build": "next build && next export",
"dev": "next",
"start": "next start",
"postexport": "node post-export.js" // ← This guy runs after the build script
}
// ...abbreviated
The contents of the post-export.js
file are the following (including the copying of _redirects):
// post-export.js
require('dotenv').config();
const fs = require('fs');
const { generateSitemap } = require('./generate-sitemap');// Copy redirects to the root of deployment folder
fs.copyFile('_redirects', './out/_redirects', err => {
if (err) throw err;
console.log('_redirects was copied to ./out/_redirects');
});// Generate the sitemap and define the target folder
// Don't forget to set the PUBLIC_DOMAIN secret in Netlify! 🕵️♀️
generateSitemap(process.env.PUBLIC_DOMAIN, './out/static/');
The Netlify deployment process kicks in after the build command has been completed and it deploys from of the ‘./out’ folder, which makes the sitemap available on your domain from the /static/sitemap.xml
path. Now simply provide that URL to, say, Google Search Console and you’re set!
If you’ve set up your CMS to use hooks to trigger a deployment, the sitemap gets updated automatically! 👌