使用create-react-app+Express部署生产环境时合并服务器遇JSON解析错误
搞定这个JSON解析错误的小妙招
嘿,我一眼就看出你遇到的Unexpected token < in JSON at position 0问题出在哪了——你的API请求/users根本没走到Express的API路由,反而被你加的通配GET路由给拦截,返回了React的index.html文件(HTML开头就是<,自然解析JSON就炸了)。
为啥会这样?
你加的这两行代码:
app.use(express.static(path.join(__dirname, 'client'))); app.get('*', function(request, response) { response.sendFile('../client/build/index.html', {global: root} ); });
Express是按路由定义的先后顺序匹配请求的。如果你的API路由(比如/users)是在这两行之后定义的,那通配*会先接住所有GET请求,包括你的API请求,直接返回index.html,根本轮不到API路由干活。另外,sendFile的相对路径也容易出问题,最好用绝对路径。
怎么修复?
第一步:调整路由顺序,让API先跑
把API路由的注册放在静态文件和通配路由前面,这样Express会先处理API请求,再管前端的静态文件和路由:
// 先引入并挂载你的用户API路由 const usersRouter = require('./routes/users'); app.use('/users', usersRouter); // 再挂载静态文件,注意要指向React打包后的build目录! app.use(express.static(path.join(__dirname, 'client/build'))); // 最后处理前端的所有路由,返回index.html app.get('*', function(request, response) { // 用绝对路径,避免相对路径坑 response.sendFile(path.join(__dirname, 'client/build', 'index.html')); });
这里要注意:静态文件得指向client/build,因为create-react-app打包后的所有产物都在这个目录里,不是client根目录哦。
第二步:确认API路由的路径是对的
你的路由文件里写的是router.get('/', ...),然后主文件里app.use('/users', usersRouter),所以完整的API路径就是/users,你前端的fetch('/users')是对的,只要路由顺序对了,就能正确匹配。
第三步:验证静态文件路径
看看你的项目结构是不是这样:
你的项目根目录/ server.js (Express主文件) client/ build/ index.html static/
如果是,那path.join(__dirname, 'client/build')就是正确的路径,要是结构不一样,就得调整路径到对应的build目录。
最后测试一下
- 先去client目录下跑
npm run build,确保build目录里有打包好的文件。 - 按上面的顺序改好Express主文件,启动服务。
- 先在浏览器直接访问
http://localhost:3000/users,看看是不是返回你的JSON数据,要是能看到,说明API路由正常了。 - 再打开前端应用,试试页面跳转和API请求,应该就不会报错啦。
内容的提问来源于stack exchange,提问作者Olivia
相关产品推荐
相关产品推荐

