DEV Community

Discussion on: Sitemap with Next.js

Collapse
 
nemuksis profile image
Paul van Dyk

Thanks for this method, i used another one which had to take advantage of experimental features, you could better this code using the sitemap package. eg;

import React from "react";
import { SitemapItem, EnumChangefreq } from "sitemap";
import { SitemapStream, streamToPromise } from "sitemap";
import { NextApiRequest, NextApiResponse, NextPageContext } from "next";

interface RouteItem extends Omit<SitemapItem, "img" | "links" | "video"> {
  title: string; // used as string title
  sitemap: boolean; // used to filter routes when construction sitemap
  navigation: boolean; // used to filter routes when construction navigation
  img?: SitemapItem["img"]; // transform type to optional
  links?: SitemapItem["links"]; // transform type to optional
  video?: SitemapItem["video"]; // transform type to optional
}

export const routes: RouteItem[] = [
  {
    title: "Landing",
    sitemap: true,
    navigation: false,
    url: "/",
    changefreq: EnumChangefreq.YEARLY,
  },
];

interface PageContext extends NextPageContext {
  req: NextApiRequest;
  res: NextApiResponse;
}

class Sitemap extends React.Component {
  static async getInitialProps({ req, res }: PageContext) {
    const hostname = "https://" + req.headers.host;
    res.setHeader("Content-Type", "text/xml");
    const smStream = new SitemapStream({ hostname });
    for (const route of routes) smStream.write(route);
    smStream.end();
    const sitemap = await streamToPromise(smStream).then((sm) => sm.toString());
    res.write(sitemap);
    res.end();
  }
}

export default Sitemap;
Enter fullscreen mode Exit fullscreen mode

@ook0 I agree with mark in using the sitemap package because it is typesafe and also has this possibility npmjs.com/package/sitemap#create-s...

Collapse
 
emil_priver profile image
Emil Privér • Edited

My goal was to use as less packages as needed, there for didn`t I use sitemap package. But I think sitemap package is a better solution

Collapse
 
nemuksis profile image
Paul van Dyk • Edited

Yes, I thought as much, I believe it's rather a choice of preference, thanks for the very informative post, both methods work great and in the end, it only comes down to a fight for bytes :)

BTW, here is the method I previously used, github.com/zeit/next.js/issues/905...
as you can see it has to leverage experimental features which are never good in a production env, so thanks for your method, I will be switching all my deployments to this method

Thread Thread
 
nemuksis profile image
Paul van Dyk • Edited

and if you would like to go a step further, I included robots using the same method.

//robots.txt.ts
import React from "react";
import { NextApiRequest, NextApiResponse, NextPageContext } from "next";

interface PageContext extends NextPageContext {
  req: NextApiRequest;
  res: NextApiResponse;
}

class Robots extends React.Component {
  static async getInitialProps({ req, res }: PageContext) {
    const hostname = "https://" + req.headers.host;
    res.setHeader("Content-Type", "text/txt");
    res.write(`
    User-agent: *
    Sitemap: ${hostname}/sitemap.xml
    `);
    res.end();
  }
}

export default Robots;
Enter fullscreen mode Exit fullscreen mode