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

MERN栈博客集成报错:SyntaxError: Unexpected token '<'

解决MERN栈博客功能中SyntaxError: Unexpected token '<'错误

你遇到的这个错误本质是前端请求API后收到的不是JSON数据,而是HTML文档(大概率是404页面或者前端的index.html),导致response.json()解析失败。结合你提供的代码和MERN栈的常见问题,给出以下排查和解决步骤:

一、核心原因分析

这个报错的直接触发点是await response.json()尝试解析HTML内容(比如<!doctype html>开头的字符串),而不是预期的JSON。通常由以下几种情况导致:

  • 前后端路由路径不匹配,后端没有找到对应的API接口,返回了前端的 fallback 页面
  • 后端路由挂载路径错误,前端请求的URL和实际API地址不符
  • 后端错误处理返回了纯文本而非JSON,导致解析失败

二、具体解决方案

1. 核对API请求路径是否正确

检查后端路由的挂载方式:
如果你的后端是这样挂载博客路由的:

// 示例:假设挂载在/api前缀下
app.use('/api/blog', blogRouter);

那前端请求的URL应该是${host}/api/blog/blogs,而不是你当前写的${host}/blog/blogs。

2. 调整后端路由顺序

MERN栈中,后端需要优先处理API路由,再处理前端静态文件和路由 fallback。确保你的后端代码顺序是:

// 1. 先配置所有API路由
app.use('/api/blog', blogRouter);
// 2. 再处理前端静态文件
app.use(express.static(path.join(__dirname, '../client/build')));
// 3. 最后处理前端路由的 fallback(返回index.html)
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, '../client/build/index.html'));
});

如果把API路由写在app.get('*', ...)之后,所有请求都会被返回index.html,自然无法获取JSON数据。

3. 统一后端错误返回格式

你的后端错误处理目前返回的是纯文本,改成JSON格式,避免前端解析异常:

router.get('/blogs', async (req, res) => {
    try {
        const blogPosts = await BlogPost.find();
        res.json({blogPosts: blogPosts});
    } catch (error) {
        // 把send改成json返回错误信息
        res.status(500).json({error: "Some Error occurred"});
    }
});

4. 前端增加响应状态校验

在解析JSON前先检查响应状态,提前捕获错误:

useEffect(() => {
    const fetchBlogs = async () => {
      try {
        const url = `${host}/blog/blogs`;
        const response = await fetch(url, {
          method: "GET",
          headers: {
            "Content-Type": "application/json",
            "authtoken": localStorage.getItem("token")
          },
        });
        // 新增:检查响应是否成功
        if (!response.ok) {
          throw new Error(`请求失败,状态码:${response.status}`);
        }
        const allblogs = await response.json();
        setBlogs(allblogs);
        setLoading(false);
        extractUniqueTags(allblogs);
      } catch (error) {
        console.error('获取博客失败:', error.message);
        setLoading(false);
      }
    };

    fetchBlogs();
    // eslint-disable-next-line
  }, []);

附:你提供的原始代码

前端获取数据代码

useEffect(() => {
    const fetchBlogs = async () => {
      try {
        const url = `${host}/blog/blogs`;
        const response = await fetch(url, {
          method: "GET",
          headers: {
            "Content-Type": "application/json",
            "authtoken": localStorage.getItem("token")
          },
        });
        const allblogs = await response.json();
        setBlogs(allblogs);
        setLoading(false);
        extractUniqueTags(allblogs);
      } catch (error) {
        console.error('Error fetching blogs:', error.message);
        setLoading(false);
      }
    };

    fetchBlogs();
    // eslint-disable-next-line
  }, []);

后端返回数据代码

router.get('/blogs', async (req, res) => {
    try {
        const blogPosts = await BlogPost.find();
        res.json({blogPosts: blogPosts});
    } catch (error) {
        res.status(500).send("Some Error occurred");
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:07:26