最近在用宝塔面板搭建一个服务时,遇到一个挺常见的问题:通过 Nginx 把域名 http://test.uonce.com/ 反向代理到本地 4000 端口的服务上,页面虽然能打开,但样式全乱了——CSS、JavaScript 和图片统统没加载出来。
打开浏览器开发者工具一看,果然一堆 404 或 Mixed Content 错误。这其实不是服务本身的问题,而是反向代理配置没处理好静态资源请求。
下面我就结合实际场景,一步步讲清楚这个问题是怎么产生的,以及怎么彻底解决它。

站长导航
优网导航旗下汇集全网优质站长工具,一站式站长工具大全导航网站
为什么反代后静态资源会“消失”?
当你用 proxy_pass 把请求转发给后端服务时,Nginx 默认只会转发路径 / 的请求。而像 .css、.js、.png 这类静态文件,往往是由前端代码里硬编码的相对或绝对路径引用的。
如果 Nginx 配置里没有专门处理这些静态资源的规则,它们可能:
- 被当成普通路径转发,但后端服务没正确响应;
- 或者因为协议不一致(比如前端是 HTTPS,后端返回 HTTP 资源),触发浏览器的 Mixed Content 安全策略,直接被拦截。
尤其是在 WordPress、Chevereto 这类 CMS 系统中,资源路径经常依赖 Host 头或协议信息来生成 URL。一旦代理层没传对头信息,后端就“懵了”,返回错误的链接。
核心解决方案:补全代理头 + 单独匹配静态资源
✅ 第一步:确保通用代理配置完整
先看基础的反代配置,很多人只写了这一段:

AI 工具导航
优网导航旗下AI工具导航,精选全球千款优质 AI 工具集
location / {
proxy_pass http://www.uonce.com:4000/;
}
这其实不够。你需要告诉后端:用户是通过你的域名、用 HTTPS 访问的。否则后端可能按 HTTP 生成资源链接,导致混合内容错误。
所以完整的通用配置应该加上几个关键头:
location / {
proxy_set_header Host $http_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; # 自动识别 http/https
proxy_pass http://www.uonce.com:4000/;
}
💡 小贴士:
$scheme会自动根据当前请求是 HTTP 还是 HTTPS 来设置值,比硬写https更灵活。
✅ 第二步:单独处理静态资源请求(可选但推荐)
虽然上面的配置通常够用,但在某些框架或旧系统中,静态资源路径可能被特殊处理。为了保险起见,可以显式匹配常见静态文件类型,并复用相同的代理逻辑:
# 显式代理静态资源,避免被其他规则干扰
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 12h; # 设置缓存时间,提升性能
proxy_set_header Host $http_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;
proxy_pass http://www.uonce.com:4000; # 注意这里末尾没有斜杠!
# 日志关闭可选,减少磁盘IO
error_log /dev/null;
access_log /dev/null;
}
⚠️ 注意:
proxy_pass地址末尾有没有/很关键!免费在线工具导航
优网导航旗下整合全网优质免费、免注册的在线工具导航大全
- 有
/:Nginx 会把location匹配的部分去掉再拼接;- 没有
/:原样转发整个 URI。
这里因为正则匹配的是完整路径(如/static/app.js),所以不要加斜杠,否则可能拼错。
✅ 第三步:如果是 HTTPS 站点,务必处理 Mixed Content
如果你的站点启用了 HTTPS,但后端服务仍返回 HTTP 链接(比如 WordPress 数据库里存的是 http://...),浏览器会直接 block 掉这些“不安全”的资源。
这时候有两个办法:
方法一:让后端知道真实协议(推荐)
在 Nginx 中加上这行,告诉后端:“用户其实是用 HTTPS 访问的”:
proxy_set_header X-Forwarded-Proto https;
然后确保你的应用(如 WordPress)能识别这个头。WordPress 用户可以在 wp-config.php 里加:
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
方法二:强制重写响应中的 HTTP 链接
如果没法改后端,可以用 Nginx 的 sub_filter 模块(需编译支持)替换 HTML 中的 http:// 为 https://,但性能开销大,不推荐作为首选。
更稳妥的做法还是从源头解决:统一使用 HTTPS 回源 + 正确设置代理头。
额外提醒:CDN 用户特别注意回源协议
如果你用了 CDN(比如 Cloudflare、腾讯云 CDN),还要检查两点:
- CDN 是否开启 HTTPS 回源?如果 CDN 用 HTTPS 对外,却用 HTTP 回源到你的服务器,同样会触发 Mixed Content。
- CDN 是否缓存了 301 重定向?有时候你设置了 HTTP → HTTPS 跳转,但 CDN 缓存了跳转响应,导致用户始终访问 HTTP 版本。
建议:CDN 后台开启“强制 HTTPS”或“HSTS”,并清空缓存测试。
最后:重启生效 & 验证
改完配置别忘了:
nginx -t # 先测试语法是否正确
systemctl reload nginx # 平滑重载,不停服务
然后打开浏览器开发者工具(F12),切换到 Network 标签,刷新页面,观察 CSS/JS 请求的状态码和协议是否正常。
如果一切顺利,页面样式就应该回来了!
总结一下
- 反向代理不只是
proxy_pass一行的事,头信息传递很关键; - 静态资源加载失败,大概率是 Host、协议或路径拼接出错;
- HTTPS 站点务必确保 全链路使用 HTTPS,避免 Mixed Content;
- 配置时注意
proxy_pass末尾斜杠的细节; - CDN 用户要同步检查回源设置。
这些问题看似琐碎,但都是线上部署的“经典坑”。踩过一次,下次就能秒解。
希望这篇整理能帮你少走弯路。有问题欢迎留言讨论!




