如何使用sitemap包在Next.js中生成动态站点地图并解决相关报错
问题根因
你的代码核心问题是Parse.Cloud.run异步调用没有加await,云函数还没返回结果、动态路由还没推入links数组,程序就已经执行到后续生成sitemap的逻辑了,所以动态路由永远不会出现在最终的站点地图里。
修复步骤
- 给异步的
Parse.Cloud.run加上await,确保动态路由获取完成后再执行后续逻辑 - 移除
Parse.Cloud.run后的.then()链式调用,改用同步写法更易维护,避免回调地狱 - 确认你的这个文件是放在Next.js的
pages/api目录下的,文件名命名为sitemap.js,这样访问/api/sitemap就能直接触发这个接口返回站点地图,不需要用到getServerSideProps,因为API路由本身就是服务端执行的。
修复后完整代码
import { SitemapStream, streamToPromise } from "sitemap"; const { Readable } = require("stream"); import { initializeParse } from '@parse/react-ssr'; initializeParse( 'https://parseapi.back4app.com', '你的Application ID', '你的JavaScript key' ); const sitemap = async (req, res) => { try { const links = [ { url: "/blogggy", changefreq: "daily", priority: 0.3 }, { url: "/explore", changefreq: "daily", priority: 0.9 } ]; const userParams = { authKey: "你的authKey" } // 加await等待云函数返回结果 const response = await Parse.Cloud.run("getAllRoutes", userParams); // 把云函数返回的动态路由推入links数组 response.forEach((handle) => { links.push({ url: `/${handle}`, changefreq: "daily", priority: 0.9, }); }); const stream = new SitemapStream({ hostname: `https://${req.headers.host}` }); res.writeHead(200, { "Content-Type": "application/xml", }); const xmlString = await streamToPromise( Readable.from(links).pipe(stream) ).then((data) => data.toString()); res.end(xmlString); } catch (e) { console.log(e); res.status(500).send(JSON.stringify(e)); } }; export default sitemap
额外注意事项
- 不需要用
getServerSideProps实现这个需求,getServerSideProps是服务端渲染页面的生命周期方法,无法直接返回application/xml类型的响应,API路由原生支持自定义响应头和响应内容,是更适合的实现方式。 - 如果你想让站点地图的路径是
/sitemap.xml而不是/api/sitemap,可以在next.config.js里加重定向规则,把/sitemap.xml指向/api/sitemap即可。 - 你当前代码里没有用到
memory-cache,不需要的话可以删除对应的import语句。 - 如果云函数调用有权限问题,确认你传入的authKey是正确的,back4app的云函数如果设置了权限校验,需要对应传入合法的sessionToken或者授权参数。
内容的提问来源于stack exchange,提问作者Aadhit Shanmugam
相关产品推荐
相关产品推荐

