Skip to content

Instantly share code, notes, and snippets.

@AndrewIngram
Last active February 17, 2023 02:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndrewIngram/29cdb0c2cdb55e022dcdb6f44ee1ecce to your computer and use it in GitHub Desktop.
Save AndrewIngram/29cdb0c2cdb55e022dcdb6f44ee1ecce to your computer and use it in GitHub Desktop.
Next.js SItemap route with streaming (requires Node 18+)
import { SitemapStream, EnumChangefreq } from "sitemap";
import { getAllPosts } from "~/data";
import { Readable } from "node:stream";
async function* getSitemapUrls(request: Request) {
const url = new URL(request.url);
const origin = `${url.protocol}//${url.host}`;
const buildUrl = (path: string) => `${origin}${path}`;
yield {
url: buildUrl("/"),
changefreq: EnumChangefreq.DAILY,
priority: 0.7,
};
for (const post of await getAllPosts()) {
yield {
url: buildUrl(`/posts/${post.slug}`),
changefreq: EnumChangefreq.DAILY,
priority: 0.7,
};
}
}
export async function GET(request: Request) {
try {
const smStream = new SitemapStream();
Readable.from(getSitemapUrls(request)).pipe(smStream);
// smStream is a node stream, so we need to turn it into a web platform one.
const reader = Readable.toWeb(smStream).getReader();
const encoder = new TextEncoder();
const stream = new ReadableStream({
async pull(controller) {
const { value, done } = await reader.read();
if (done) {
return controller.close();
}
controller.enqueue(encoder.encode(value));
},
});
return new Response(stream, {
headers: {
"Content-Type": "application/xml",
},
status: 200,
});
} catch (e) {
console.error(e);
return new Response("", {
status: 500,
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment