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

如何配置Nginx适配React/React Router?遇unexpected token <错误求助

解决Nginx反向代理React/Express应用时的unexpected token <错误

兄弟我太懂这个坑了!你碰到的unexpected token <错误,结合你说的main.chunk.js返回index.html的情况,百分百是Nginx的路由配置没处理好React Router的单页特性,同时和Express的代理规则冲突了——我之前踩过一模一样的坑,给你一步步拆解解决:

问题根源

当你用React Router的browserHistory模式时,所有前端路由请求(比如/app/profile)都会被Nginx当成静态资源请求;如果Nginx没配置正确的fallback规则,或者错误地把静态资源请求(比如/main.chunk.js)转发给了Express,Express就会返回index.html(因为你可能配置了*路由返回index.html),浏览器拿到HTML却当成JS解析,自然就会报unexpected token <错误。

解决方案

1. 修正Nginx配置,区分静态资源和API代理

核心是让Nginx直接处理前端静态资源,只把API请求转发给Express,同时正确处理React Router的fallback。

假设你的静态React应用部署在/var/www/static-react,React/Express应用的build产物在/var/www/react-express/build,Express监听5001端口,给你一个参考配置:

server {
    listen 80;
    server_name your_domain_or_ip;

    # 处理根路径的静态React应用
    location / {
        root /var/www/static-react;
        # 先找对应文件,找不到返回index.html(处理React Router)
        try_files $uri $uri/ /index.html;
    }

    # 处理React/Express应用(假设访问路径是/app)
    location /app {
        # 让Nginx直接serve build后的静态资源
        root /var/www/react-express/build;
        # 注意这里的fallback是/app/index.html,不是根路径的!
        try_files $uri $uri/ /app/index.html;

        # 嵌套配置:只把/app/api开头的请求转发给Express
        location ~ /app/api {
            proxy_pass http://localhost:5001;
            # 这些header配置保证Express能正确获取请求信息
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }

    # 如果你的Express API直接在根路径/api,单独配置这个
    # location /api {
    #     proxy_pass http://localhost:5001;
    #     proxy_set_header Host $host;
    #     proxy_set_header X-Real-IP $remote_addr;
    #     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    #     proxy_set_header X-Forwarded-Proto $scheme;
    # }
}

关键注意点:

  • try_files的最后一个参数一定要对应你的React应用部署路径,比如部署在/app下就写/app/index.html,绝对不能写根路径的/index.html,否则会加载错误的静态资源。
  • 一定要把API请求的路由单独拆分出来,避免静态资源请求被转发给Express。

2. 调整Express的路由顺序

确保Express先处理静态资源,再处理API路由,最后才是单页应用的fallback(如果需要)。你的index.js应该改成这样:

const express = require('express');
const path = require('path');
const app = express();

// 1. 优先serve React build后的静态文件
app.use(express.static(path.join(__dirname, 'build')));

// 2. 然后定义所有API路由
app.get('/api/hello', (req, res) => {
    res.json({ message: 'Hello from Express!' });
});

// 3. 最后处理所有其他请求,返回index.html(仅当Express需要直接serve单页应用时)
app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(5001, () => {
    console.log('Server running on port 5001 🚀');
});

为什么要这么做:如果Nginx把静态资源请求转发给Express,Express会先尝试返回对应的静态文件,而不是直接返回index.html——不过最好还是让Nginx直接处理静态资源,这样性能更好,也避免冲突。

3. 验证配置并重启服务

  • 先检查Nginx配置是否合法:sudo nginx -t
  • 如果提示test is successful,重启Nginx:sudo systemctl restart nginx
  • 清除浏览器缓存(或者用隐私模式打开),避免之前缓存的错误HTML影响测试。

最后验证

现在通过Nginx访问你的React/Express应用,打开浏览器控制台,查看main.chunk.js的返回内容——应该是JS代码而不是index.html,unexpected token <错误也会消失,同时React Router的路由也能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 10:35:41