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

Next.js生成动态Sitemap部署Vercel时遇JSON解析及404错误求助

Next.js动态Sitemap部署Vercel报错「SyntaxError: Unexpected token < in JSON at position 0」解决方法

问题描述

我尝试用Next.js生成动态Sitemap,本地运行一切正常,但部署到Vercel时出现「SyntaxError: Unexpected token < in JSON at position 0」错误。

我的源代码如下:

export default async function sitemap() {
  const res = await fetch('https://example.com/api/games');
  const games = await res.json();
  const gameUrls = games.map((game) => ({
    url: `http://localhost:3000/Games/${encodeURIComponent(game.title)}`,
    lastModified: new Date().toISOString(),
  }));
  return [...gameUrls];
}

本地运行时将fetch地址改为http://localhost:3000/api/games就正常,但部署后打印响应结果显示状态码为404,响应信息如下:

Response {
  [Symbol(realm)]: null,
  [Symbol(state)]: {
    aborted: false,
    rangeRequested: false,
    timingAllowPassed: true,
    requestIncludesCredentials: true,
    type: 'default',
    status: 404,
    timingInfo: {
      startTime: 11159.292941000022,
      redirectStartTime: 0,
      redirectEndTime: 0,
      postRedirectStartTime: 11159.292941000022,
      finalServiceWorkerStartTime: 0,
      finalNetworkResponseStartTime: 0,
      finalNetworkRequestStartTime: 0,
      endTime: 0,
      encodedBodySize: 0,
      decodedBodySize: 0,
      finalConnectionTimingInfo: null
    },
    cacheState: '',
    statusText: 'Not Found',
    headersList: HeadersList {
      cookies: null,
      [Symbol(headers map)]: [Map],
      [Symbol(headers map sorted)]: null
    },
    urlList: [ [URL] ],
    body: { stream: undefined }
  },
  [Symbol(headers)]: HeadersList {
    cookies: null,
    [Symbol(headers map)]: Map(15) {
      'access-control-allow-origin' => [Object],
      'age' => [Object],
      'cache-control' => [Object],
      'connection' => [Object],
      'content-disposition' => [Object],
      'content-encoding' => [Object],
      'content-type' => [Object],
      'date' => [Object],
      'etag' => [Object],
      'server' => [Object],
      'strict-transport-security' => [Object],
      'x-matched-path' => [Object],
      'x-vercel-cache' => [Object],
      'x-vercel-id' => [Object],
      'transfer-encoding' => [Object]
    },
    [Symbol(headers map sorted)]: null
  }
}

错误原因分析

  1. API路径无效:部署后请求https://example.com/api/games返回404,说明该路径在Vercel环境下不存在,可能是API路由配置错误或域名未正确关联。
  2. JSON解析失败:404响应返回的是HTML格式的错误页面,而非预期的JSON数据,调用res.json()时会解析HTML开头的<符号,直接触发语法错误。
  3. 域名硬编码问题:生成的Sitemap中使用localhost域名,部署后搜索引擎无法访问生产环境页面,同时也暴露了本地开发路径的不合理性。

解决方案

1. 修正API请求方式

避免硬编码外部域名,优先直接调用内部业务逻辑(更高效且无路径问题),或使用Vercel环境变量获取生产域名:

// 方式1:直接导入API逻辑(推荐)
import getGames from '@/lib/getGames';

export default async function sitemap() {
  const games = await getGames();
  const siteUrl = process.env.NODE_ENV === 'production' ? `https://${process.env.VERCEL_URL}` : 'http://localhost:3000';
  
  const gameUrls = games.map((game) => ({
    url: `${siteUrl}/Games/${encodeURIComponent(game.title)}`,
    lastModified: new Date().toISOString(),
  }));
  return [...gameUrls];
}

// 方式2:用环境变量拼接API路径
export default async function sitemap() {
  const baseUrl = process.env.NODE_ENV === 'production' ? `https://${process.env.VERCEL_URL}` : 'http://localhost:3000';
  const res = await fetch(`${baseUrl}/api/games`);
  
  // 先检查响应状态,避免解析错误页面
  if (!res.ok) {
    throw new Error(`API请求失败,状态码:${res.status}`);
  }
  
  const games = await res.json();
  const gameUrls = games.map((game) => ({
    url: `${baseUrl}/Games/${encodeURIComponent(game.title)}`,
    lastModified: new Date().toISOString(),
  }));
  return [...gameUrls];
}

2. 替换本地域名

生成Sitemap的URL时,统一使用生产环境域名,通过process.env.VERCEL_URL自动获取Vercel分配的域名,或手动配置自定义域名环境变量。

3. 添加错误处理

在解析JSON前先校验响应状态,提前捕获API请求失败的情况,避免后续解析错误。

内容的提问来源于stack exchange,提问作者boketeボケて

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:53:29