You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。

  1. 修改nuxt.config.js,移除原有的sitemap()配置,添加serverMiddleware:
export default {
  // ...其他配置
  serverMiddleware: [
    { path: '/sitemap.xml', handler: './server-middleware/sitemap.js' }
  ]
}
  1. 创建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生成失败');
  }
};
  1. 安装依赖:
npm install sitemap node-cache

方案二:定时生成静态Sitemap文件

使用定时任务定期拉取CMS数据,生成静态sitemap.xml.gz文件到Nuxt的static目录,由Nuxt托管静态文件。

  1. 安装定时任务依赖:
npm install node-schedule sitemap
  1. 创建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();
  1. 修改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'
      }
    }
  ]
};
  1. 启动服务:
pm2 start ecosystem.config.js

注意事项

  • 方案一适合需要实时(或准实时)更新的场景,方案二更适合CMS更新频率不高、追求性能的场景。
  • 确保CMS接口ARTICLE_URL能正确返回最新的文章数据,且权限配置正确。

内容的提问来源于stack exchange,提问作者Jarrod

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:25:41