Generating sitemaps for react apps is much more complex that it should be.
If your app is basic with a few routes, then you can add a simple static sitemap file inside your public folder and call it done.
I have somewhat dynamic content, so I need a somewhat dynamic solution, and thankfully my hosting provider netlify has free netlify function.
1. Return static data
Netlify will not currently allow a streaming response, so we have to figure out a static xml response.
Inside your functions folder, add /functions/sitemap.js
exports.handler = function(event, context, callback) {
var xml_content = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
`<url><loc>https://www.blairanderson.co/</loc></url>`,
// `<url><loc>add more pages here</loc></url>`,
"</urlset>"
];
callback(null, {
statusCode: 200,
headers: { "Content-Type": "text/xml" },
body: xml_content.join("\n")
});
};
push to netlify, and this is a perfectly acceptable sitemap to submit to google!
2. Return dynamic data
If any part of your site is dynamic, maybe you have a CRUD form and want to have a page for each comment that is user-generated-content.
You might want use an API to hold your comments, and return them when people visit.
This is a scenario you might want to add them to a sitemap, and also use that API to fetch the full list of comments or something like that.
var https = require("https");
var API_DATA_URL = "https://www.someexampledata.com/comments.json";
exports.handler = function(event, context, callback) {
var xml_content = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
];
https
.get(API_DATA_URL, resp => {
let data = "";
// A chunk of data has been recieved.
resp.on("data", chunk => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on("end", () => {
var json = JSON.parse(data);
var list = json.listOfExampleThings.map(function(el) {
return `<url><loc>https://www.site.com/comment/${el.id}</loc></url>`;
});
var body = xml_content
.concat(list)
.concat("</urlset>")
.join("\n");
callback(null, {
statusCode: 200,
headers: { "Content-Type": "text/xml" },
body: body
});
});
})
.on("error", err => {
console.log("Error: " + err.message);
});
};
The best part about this is that you do not need to worry about any package management or modules because https
is built into node!