Nuxt 2 SSR模式下Sitemap无法定时更新问题求助
Nuxt 2 SSR Sitemap 定时更新问题解决
你的Nuxt 2 SSR项目通过pm2启动,已配置从无头CMS拉取文章路由生成sitemap,设置了cacheTime: 15分钟,但CMS发布新文章后,等待15分钟sitemap仍未同步新路由。
问题根源
Nuxt官方sitemap模块的sitemap()配置函数,在server模式(target: 'server')下只会在服务启动时执行一次,生成的路由会一直存在内存中。cacheTime是发送给爬虫的HTTP缓存头,仅用于告诉爬虫“该sitemap内容在15分钟内无需重新请求”,并不会触发服务端定时重新拉取CMS数据。由于pm2启动后服务持续运行,不会自动重启,因此新文章路由无法自动同步。
解决方案
以下两种方案可实现sitemap定时更新:
方案一:通过Server Middleware动态生成Sitemap
自定义server middleware处理sitemap.xml请求,每次请求时(或结合本地缓存)重新拉取CMS数据生成sitemap。
- 修改nuxt.config.js,移除原有的
sitemap()配置,添加serverMiddleware:
export default { // ...其他配置 serverMiddleware: [ { path: '/sitemap.xml', handler: './server-middleware/sitemap.js' } ] }
- 创建server-middleware/sitemap.js,编写动态生成逻辑:
const axios = require('axios'); const { SitemapStream, streamToPromise } = require('sitemap'); const { createGzip } = require('zlib'); const NodeCache = require('node-cache'); // 本地缓存15分钟,避免频繁请求CMS const sitemapCache = new NodeCache({ stdTTL: 15 * 60 }); module.exports = async (req, res) => { try { let allRoutes = sitemapCache.get('sitemap_routes'); if (!allRoutes) { // 拉取CMS文章路由 const articleRoutes = []; const now = new Date(); const response = await axios.get(process.env.ARTICLE_URL); response.data.data.forEach(route => { const publishDate = new Date(route.publish_date); if (publishDate < now) { articleRoutes.push({ url: `/${route.id}`, lastmod: publishDate.toISOString() }); } }); // 静态基础路由(按需添加) const baseRoutes = [ { url: '/', lastmod: new Date().toISOString() }, { url: '/about', lastmod: new Date().toISOString() } ]; allRoutes = [...baseRoutes, ...articleRoutes]; sitemapCache.set('sitemap_routes', allRoutes); } // 生成sitemap并返回 const smStream = new SitemapStream({ hostname: 'www.foo.bar' }); const pipeline = smStream.pipe(createGzip()); allRoutes.forEach(route => smStream.write(route)); smStream.end(); res.setHeader('Content-Type', 'application/xml'); res.setHeader('Content-Encoding', 'gzip'); const sitemap = await streamToPromise(pipeline); res.send(sitemap); } catch (error) { console.error('Sitemap生成失败:', error); res.status(500).send('Sitemap生成失败'); } };
- 安装依赖:
npm install sitemap node-cache
方案二:定时生成静态Sitemap文件
使用定时任务定期拉取CMS数据,生成静态sitemap.xml.gz文件到Nuxt的static目录,由Nuxt托管静态文件。
- 安装定时任务依赖:
npm install node-schedule sitemap
- 创建cron/sitemap.js,编写定时生成逻辑:
const axios = require('axios'); const { SitemapStream, streamToPromise } = require('sitemap'); const fs = require('fs'); const path = require('path'); const { createGzip } = require('zlib'); const schedule = require('node-schedule'); const generateSitemap = async () => { try { const articleRoutes = []; const now = new Date(); const response = await axios.get(process.env.ARTICLE_URL); response.data.data.forEach(route => { const publishDate = new Date(route.publish_date); if (publishDate < now) { articleRoutes.push({ url: `/${route.id}`, lastmod: publishDate.toISOString() }); } }); const baseRoutes = [ { url: '/', lastmod: new Date().toISOString() } ]; const allRoutes = [...baseRoutes, ...articleRoutes]; const smStream = new SitemapStream({ hostname: 'www.foo.bar' }); const pipeline = smStream.pipe(createGzip()); allRoutes.forEach(route => smStream.write(route)); smStream.end(); const sitemap = await streamToPromise(pipeline); // 写入static目录,Nuxt自动托管 fs.writeFileSync(path.resolve(__dirname, '../static/sitemap.xml.gz'), sitemap); console.log('Sitemap已更新'); } catch (error) { console.error('Sitemap生成失败:', error); } }; // 每15分钟执行一次(cron表达式:*/15 * * * *) schedule.scheduleJob('*/15 * * * *', generateSitemap); // 服务启动时先执行一次 generateSitemap();
- 修改pm2配置文件(ecosystem.config.js),同时启动Nuxt服务和定时任务:
module.exports = { apps: [ { name: 'nuxt-app', script: 'npm run start', env: { NODE_ENV: 'production' } }, { name: 'sitemap-cron', script: 'node cron/sitemap.js', env: { NODE_ENV: 'production' } } ] };
- 启动服务:
pm2 start ecosystem.config.js
注意事项
- 方案一适合需要实时(或准实时)更新的场景,方案二更适合CMS更新频率不高、追求性能的场景。
- 确保CMS接口
ARTICLE_URL能正确返回最新的文章数据,且权限配置正确。
内容的提问来源于stack exchange,提问作者Jarrod
相关产品推荐
相关产品推荐

