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

Next.js+Sanity部署Vercel报错:JSON响应无效(Unexpected token T)

解决方案

1. 修复fetchExperiences函数的变量名错误

你的fetchExperiences函数存在明显笔误:定义了projects变量,但返回的是未声明的experience,这会触发运行时错误,导致API返回非JSON格式的错误文本(比如以"TypeError"开头,对应报错里的Unexpected token T)。

修改后代码:

import {Experience} from '../typings'
export const fetchExperiences = async () =>{
    const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/getExperience`)
    // 先校验响应状态,提前拦截错误
    if (!res.ok) {
        throw new Error(`API请求失败: ${res.status}`)
    }
    const data = await res.json()
    const experiences:Experience[] = data.experience

    return experiences
}

2. 简化API路由的JSON返回逻辑

getExperience.ts里的JSON.parse(JSON.stringify({experience}))完全多余,Next.js的res.json()会自动处理对象序列化,多余的序列化/反序列化可能引发意外问题。同时添加错误捕获,避免返回非JSON内容:

修改后代码:

import type{NextApiRequest,NextApiResponse} from 'next'
import {groq} from 'next-sanity';
import {sanityClient} from '../../sanity';
import {Experience} from '../../typings'
const query = groq`
*[_type == "experience"]{
    ...,
    technologies[]->
}
`;
type Data ={
    experience:Experience[]
}
export default async function handler(
    req:NextApiRequest,
    res:NextApiResponse<Data>,
){
    try {
        const experience:Experience[]= await sanityClient.fetch(query)
        res.status(200).json({experience})
    } catch (err) {
        // 捕获错误并返回合法JSON
        res.status(500).json({ experience: [], error: '获取数据失败' })
    }
}

3. 优化getStaticProps的数据源获取(可选但推荐)

在getStaticProps中无需通过HTTP请求调用自身API,直接在服务端调用Sanity查询逻辑即可,既能避免环境变量配置问题,还能提升构建效率:

修改index.ts的getStaticProps:

import { groq } from 'next-sanity';
import { sanityClient } from '../sanity';
import { Experience, Skill, Project, Social } from '../typings';

// 单独提取各数据的GROQ查询
const experienceQuery = groq`
*[_type == "experience"]{
    ...,
    technologies[]->
}
`;
const skillQuery = groq`/* 替换为你的技能查询语句 */`;
const projectQuery = groq`/* 替换为你的项目查询语句 */`;
const socialQuery = groq`/* 替换为你的社交链接查询语句 */`;

export const getStaticProps: GetStaticProps<Props> = async() => {
  try {
    const experience : Experience[] = await sanityClient.fetch(experienceQuery);
    const skills : Skill[] = await sanityClient.fetch(skillQuery);
    const projects : Project[] = await sanityClient.fetch(projectQuery);
    const socials : Social[] = await sanityClient.fetch(socialQuery);
    
    return{
      props:{
        experience,
        skills,
        projects,
        socials,
      },
      revalidate:10
    }
  } catch (err) {
    console.error('构建时获取数据失败:', err);
    // 返回默认空数据避免构建失败
    return{
      props:{
        experience: [],
        skills: [],
        projects: [],
        socials: [],
      },
      revalidate:10
    }
  }
}

4. 验证环境变量配置

确保Vercel后台的NEXT_PUBLIC_BASE_URL已正确设置为你的部署域名(比如https://portfolio2-1-wn3v.vercel.app),并重新部署使配置生效。

排查思路总结

Unexpected token T这类报错通常说明API返回的不是合法JSON,而是文本格式的错误信息(比如"TypeError: experience is not defined"),优先排查:

  • 代码中的变量名错误、未捕获的异常
  • API路由是否有完善的错误捕获逻辑
  • 部署日志中的具体错误栈信息

内容的提问来源于stack exchange,提问作者Nejc Lampič

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 03:31:50