My site contains several dynamic routes and uses the getStaticPaths and getStaticProps hooks from the 9.3 release. I'd like to generate a sitemap for it. It's quite hard.
I'd like some way of accessing the list of paths/pages generated during the build step. The information I need is printed to the CLI during "next build" but there's no way (I think) for the developer to tap into it:

There are several other issues on here describing incomplete solutions that only work for static pages. My page has several dynamic routes ([blog.tsx]). I'm not aware of any solution that works.
Next.js is 馃敟, this is the one thing tripping me up 馃
It would be awesome if nextjs supports this out of the box 馃殌
What would be the ideal format of the sitemap? Will a simple JSON containing all the routes do?
I can whip up a PR for it
Solution based on information from the build manifest is not ideal, because pages with getServerSideProps, getInitialProps and getStaticProps with fallback option will not be supported. It is much better to create the sitemap on the fly (the approach was described in discussions multiple times) because only you know your web application better.
Here is my boilerplate from pages/sitemap.xml.jsx:
import { renderToStaticMarkup } from "react-dom/server";
const SitemapIndex = () => null;
const Sitemap = ({ pages, origin }) => {
/*
* NOTE: <?xml ?> is optional preamble from the spec,
* UTF-8 is the default
* version 1.0 is the default
*/
return (
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{pages?.map((page, index) => {
return (
<url key={index}>
<loc>{[origin, page?.fullSlug].join("/")}</loc>
<lastmod>{page?.publishedAt}</lastmod>
</url>
);
})}
</urlset>
);
};
export const getServerSideProps = async ({ res }) => {
const pages = // TODO: fetch your pages
const origin = // TODO: place your origin
res.setHeader("Content-Type", "text/xml");
res.write(renderToStaticMarkup(<Sitemap pages={pages} origin={origin} />));
res.end();
return {
props: {},
};
};
export default SitemapIndex;
I think this is related: How to create a routes list component
@rokinsky good point. It would for there to be a solution that works for the classic SSG/getStaticPaths approach though, which is an increasingly popular usage pattern among Next.js users.
@vriad Check with-next-sitemap example. This might be the solution you're looking for.
@iamvishnusankar Your solution is great, but will not work if there are mixed static/dynamic pages like:
//about/posts/[id].js where posts must be fetched on every server request (getServerSideProps)@arvigeus Yes, you're correct. next-sitemap wont work for dynamic pages rendered using getServerSideProps (it works for getStaticProps though).
Its because the package relies on build and pre-render manifest files which are only available after next build.
Also, if you're parsing the same set of posts every time, wouldn't it be better to pre-render them to reduce server load? (Or use Incremental Static Regeneration)
My proposal would be:
On build check if there is /pages/sitemap.xml.js. If file does not exist, skip sitemap generation
If file contains getStaticProps, the function will receive one parameter: list of objects with data for each sitemap item. The function will return the same type of array of object (e.g. allow modification, adding new paths, omitting, etc). On build this will be translated to sitemap.xml in output directory and robots.txt
If file contains getServerSideProps it will be mostly the same, serverside executed on every request, while allowing async loading of more pages. Response type will be set to xml
If given page has [foo].js as name, it will check for getStaticPaths and populate entries from there. If getStaticPaths is missing, display warning.
Bonus: Allow partial sitemaps using arbitrary files with specific exports
Most helpful comment
Solution based on information from the build manifest is not ideal, because pages with
getServerSideProps,getInitialPropsandgetStaticPropswithfallbackoption will not be supported. It is much better to create the sitemap on the fly (the approach was described in discussions multiple times) because only you know your web application better.Here is my boilerplate from
pages/sitemap.xml.jsx: