I am trying to create a sitemap for the the project I'm working on and currently using next-sitemap to generate. The problem with this approach and pretty much another solution I found is that the sitemap is generated for the pages that are created during build time.
My use-case requires adding URL parameters in the sitemap as well which do not generate new pages during build time.
This is also the closest approach I think that should work but I will need to access the JSON data for each dynamic page generated during build time.
/pages/sitemap.xml.js
const staticPages = fs
.readdirSync("pages")
.filter((staticPage) => {
return ![
"_app.js",
"_document.js",
"_error.js",
"sitemap.xml.js",
].includes(staticPage);
})
.map((staticPagePath) => {
return `${baseUrl}/${staticPagePath}`;
});
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${staticPages
.map((url) => {
return `
<url>
<loc>${url}</loc>
<lastmod>${new Date().toISOString()}</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
`;
})
.join("")}
</urlset>
`
So apparently Next.js saves all the JSON of each dynamic page at .next/server/pages/dynamicPage and we can use node fs to read the files and then parse them. This solved the issue.
So the approach which worked for my use-case:
const staticPages = fs
.readdirSync('.next/server/pages/scheme')
.filter((file) => path.extname(file).toLowerCase() === '.json');
const schemeFiles = ['https://schemes.openbudgetsindia.org'];
staticPages.forEach((staticPagePath) => {
const schemeName = staticPagePath.split('.')[0];
schemeFiles.push(
`https://schemes.openbudgetsindia.org/scheme/${schemeName}`
);
const schemeObj = JSON.parse(
fs.readFileSync(`.next/server/pages/scheme/${staticPagePath}`, 'utf8')
);
const { indicators } = schemeObj.pageProps.scheme.metadata;
indicators.forEach((indicator) =>
schemeFiles.push(
`https://schemes.openbudgetsindia.org/scheme/${schemeName}?indicator=${indicator}`
)
);
});
After that, simply create the XML data:
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${staticPages
.map((url) => {
return `
<url>
<loc>${url}</loc>
<lastmod>${new Date().toISOString()}</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
`;
})
.join("")}
</urlset>
res.setHeader('Content-Type', 'text/xml');
res.write(sitemap);
res.end();