核心问题是静态资源请求被ThinkPHP路由劫持而非Nginx直供,需确保资源放public/static/、Nginx用alias配置location ^~ /static/并置于php规则前、响应头为text/css而非text/html。

前后端分离部署后静态资源访问不到,核心问题不是路径写错,而是请求没被 Web 服务器直接响应,反而误进了 ThinkPHP 路由系统——结果框架试图找一个叫 PublicController 或 CssController 的控制器,自然报 404。
确认静态资源是否放在 public 目录下
ThinkPHP 6/8 强制要求 Web 根目录指向 public/。所有可被浏览器直接访问的文件(CSS、JS、图片等)必须放在 public/ 及其子目录里,比如:
public/static/css/app.csspublic/images/logo.png-
public/index.html(如果是前端打包产物)
如果把前端 dist 文件夹直接丢在 app/、runtime/ 或项目根目录,Nginx 根本无法定位,必然 404。
检查 Nginx 静态资源 location 规则顺序
Nginx 匹配规则是按配置顺序从上到下执行的。如果 location ~ \.php$ 出现在 location ^~ /static/ 前面,所有 /static/xxx.js 请求都会先被 PHP 处理,而不是返回文件。
立即学习“PHP免费学习笔记(深入)”;
正确写法(必须放在所有 ~ \.php$ 块之前):
location ^~ /static/ {
alias /var/www/myapp/public/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
location ^~ /images/ {
alias /var/www/myapp/public/images/;
expires 7d;
}
注意:用 alias,别用 root。若用 root /var/www/myapp/public;,实际会去找 /var/www/myapp/public/static/static/xxx.css,多了一层 static。
验证静态资源是否被框架劫持
在浏览器打开一个 CSS 地址,比如 https://yoursite.com/static/css/app.css,然后看响应头:
- 如果
Content-Type: text/css且有Cache-Control,说明 Nginx 直接返回了文件 ✅ - 如果
Content-Type: text/html或返回的是 ThinkPHP 的“找不到路由”页面 ❌,说明请求被重写到了 index.php
此时立刻检查:location / 块里的 try_files 是否漏掉了 $uri 判断?是否把 location ^~ /static/ 写在了错误位置?
前端资源引用路径要适配部署环境
前后端分离时,前端通常独立构建(如 Vue CLI 打包),不能依赖 ThinkPHP 的 url() 函数。关键点:
- 构建时配置
publicPath:Vue CLI 设vue.config.js中publicPath: '/'(根部署)或'/admin/'(子目录) - 确保 HTML 中引入的 JS/CSS 路径是相对根路径的,例如
<link href="/static/css/app.css">,不是/public/static/... - 如果部署在子目录(如
https://site.com/myapp/),Nginx 的location和前端publicPath必须一致,否则路径全错



















