nginx通过location匹配静态资源后缀并用root指向public目录直接处理,避免经php-fpm;thinkphp需配置app.asset_url启用cdn,cdn回源须按url特征精准缓存,防止动态请求误入。

动静资源怎么让Nginx直接处理,不走ThinkPHP
核心是把 public 目录下的静态文件(.js、.css、.png 等)从PHP-FPM流程里摘出来,由Nginx自己读取并返回。否则每次请求都进 index.php,浪费CPU还拖慢响应。
关键在Nginx配置里加一段明确的 location 匹配规则,优先级要高于PHP的 location ~ \.php$:
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
root /var/www/your-project/public;
}
- 必须用
root(不是alias),因为匹配路径是相对URL的,比如访问/static/app.js,Nginx会拼成/var/www/your-project/public/static/app.js -
expires 1y和immutable是CDN友好组合,避免浏览器反复校验 - 别漏掉
woff2?这种字体后缀,否则字体404,页面文字变方块
ThinkPHP里生成静态资源URL时怎么指向CDN域名
默认 asset() 或 url() 生成的是站内相对路径或当前域名地址,要让它输出CDN前缀,得改配置,不能靠硬编码或全局替换。
ThinkPHP 6+ 支持通过 app.asset_url 配置项统一接管静态资源基础路径:
// config/app.php
'app' => [
'asset_url' => 'https://cdn.example.com',
],
- 这个值只影响
asset()函数,不影响url()(那是路由用的) - 如果CDN有多个子域名(如
cdn1.example.com、cdn2.example.com),得自己写个轮询函数封装asset(),别指望框架自动做负载 - 本地开发时建议设为空字符串或
null,避免开发环境也发CDN请求——Nginx没配好就全404
为什么Nginx转发后CSS/JS 404,但图片正常
常见原因是路径层级错位:ThinkPHP项目结构里,静态资源实际在 public/static/ 下,但你写的 root 指向了 public,而Nginx又没把URL里的 /static/ 显式映射进去。
典型错误配置:
location /static/ {
root /var/www/your-project; // ❌ 错!这会让Nginx找 /var/www/your-project/static/
}
正确做法是保持 root 指向 public,然后靠URL路径自然落到对应子目录:
location /static/ {
root /var/www/your-project/public; // ✅ 对!访问 /static/app.js → /public/static/app.js
}
- 别在
root路径里手动拼/static,那是alias的事,容易搞混 - 检查浏览器开发者工具的Network面板,看404请求的真实URL和Nginx error log里报的“open() failed”路径是否一致,这是最准的定位方式
- 如果用了
url()生成静态路径(比如误用url('static/app.js')),那永远走不到CDN,因为那是路由解析,不是资源定位
CDN回源怎么避免把动态请求也甩过去
CDN必须只缓存静态资源,不能把 /api/user 或 /index.php?s=/user/info 这类动态请求也缓存或回源到静态服务器上,否则用户看到的就是过期数据甚至500页。
最稳妥的做法是在CDN控制台或配置里,按URL特征设置缓存策略,例如:
- 匹配
*.js, *.css, *.png, *.jpg→ 缓存1年,状态码200/304生效 - 匹配
/api/*, /index.php*, /s=*→ 不缓存,强制透传 - 所有带
Cookie或Authorization请求头的 → 默认不缓存(多数CDN自动这么做,但得确认)
特别注意ThinkPHP的URL模式:如果你用的是PATH_INFO模式(如 /user/profile),CDN无法单靠后缀判断是否静态,必须配合Nginx的 try_files 或 fastcgi_pass 规则,确保只有真实存在的静态文件才被Nginx直出,其余全部交给PHP处理——CDN只认最终响应头里的 Cache-Control,它不管你是怎么生成的。
动静分离真正卡点不在配置多难,而在「谁该负责判定这个请求是不是静态」——Nginx得先拦住,CDN才不会瞎缓存;而ThinkPHP的路由机制一旦介入,就再没机会让Nginx插手了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











