Node.js+React部署Ubuntu Nginx后静态资源404问题求助
路径加载404问题排查与解决思路
环境与代码
技术栈
- Node.js(Express)后端 + React前端
- 部署环境:DigitalOcean Ubuntu 22.04 + Nginx
Express服务器代码(main.js)
// main.js const Port_TCP = 3005; const express = require('express'); const path = require("path"); let app = express(); app.use(express.json()); app.use(express.static(__dirname + '/public')); app.set('port', Port_TCP); app.get("*", function(req, res) { res.sendFile(path.join(__dirname, '/public/index.html')) }) app.listen(Port_TCP);
前端入口文件(public/index.html)
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>My website</title> <link href="css/app.css" rel="stylesheet"> <link rel="icon" type="image/x-icon" href="imgs/ico.png"> </head> <body> <!-- React root DOM --> <div id="MainRouter"></div> <!-- React JS --> <script type="application/javascript" src="js/app.js" defer></script> </body> </html>
问题表现
- 本地Windows环境运行完全正常
- 部署到Ubuntu服务器后,index.html能加载,但所有静态资源报404:
GET https://my-website.com/css/app.css net::ERR_ABORTED 404 (Not Found)
GET https://my-website.com/js/app.js net::ERR_ABORTED 404 (Not Found)
标签图标同样无法找到
补充信息
- 服务器上删除
app.get("*")代码块后仍能访问页面,但本地这么做会出现502错误 - 项目文件夹结构:
/main.js (server) /mix-manifest.json /package.json /package-lock.json watcher.js (for nodemon) webpack.mix.js /js and /sass folder (which contain react project) /public/ /public/index.html /public/css/app.css /public/js/app.js /public/imgs/
- Nginx配置(/etc/sites-available):
server { root /var/www/mywebsite.fr/public; index index.html index.htm index.nginx-debian.html; server_name mywebsite.fr www.mywebsite.fr; location / { proxy_pass http://localhost:3005; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; try_files $uri $uri/ =404; } listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/mywebsite.fr/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/mywebsite.fr/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { if ($host = www.mywebsite.fr) { return 301 https://$host$request_uri; } # managed by Certbot if ($host = mywebsite.fr) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name mywebsite.fr www.mywebsite.fr; return 404; # managed by Certbot }
解决思路
1. 修复Nginx配置冲突
当前Nginx同时设置了root指向静态目录和proxy_pass转发请求,导致静态资源请求被双重处理,出现冲突。两种可选方案:
- 方案一:完全由Express托管静态资源
删除Nginx中的root和index配置,同时移除location /里的try_files $uri $uri/ =404;,让所有请求都转发给Express处理:location / { proxy_pass http://localhost:3005; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } - 方案二:Nginx直接处理静态资源
新增location匹配静态资源后缀,让Nginx直接返回文件,剩余请求转发给Express:location ~* \.(css|js|png|ico)$ { root /var/www/mywebsite.fr/public; expires 30d; } location / { proxy_pass http://localhost:3005; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; }
2. 优化Express静态资源路径写法
Windows与Linux路径分隔符存在差异,建议使用path.join统一处理路径,避免潜在兼容问题:
// 替换原express.static行 app.use(express.static(path.join(__dirname, 'public')));
同时检查服务器public目录权限,确保Node进程有读取权限:
sudo chmod -R 755 /var/www/mywebsite.fr/public sudo chown -R www-data:www-data /var/www/mywebsite.fr/public
3. 验证静态资源实际存在性
登录服务器确认/var/www/mywebsite.fr/public/css/app.css、/var/www/mywebsite.fr/public/js/app.js等文件是否存在且内容正确,排查部署时是否遗漏打包文件或webpack打包路径错误。
4. 调整路由 fallback优先级
Express中express.static的优先级高于路由,正常情况下静态资源会被优先返回,但Nginx的try_files会导致本地找不到文件时直接返回404,跳过转发给Express的步骤,因此必须移除该行配置。
内容的提问来源于stack exchange,提问作者koesys
相关产品推荐
相关产品推荐

