生产环境应禁用hyperf静态处理,改由nginx托管/static/路径下的资源,配置alias、缓存头、gzip及动静分离,避免后缀匹配误伤api,并彻底清除hyperf中兜底静态路由。

Hyperf 默认不托管静态资源,直接用 Swoole 处理 public/ 下的 JS/CSS/图片,性能远不如 Nginx,也绕过了浏览器缓存、gzip、HTTP/2 等关键能力。真要上生产,必须把静态资源交还给 Nginx —— Swoole 只该专注动态请求。
Hyperf 里开 enable_static_handler 是个误区
Hyperf 基于 Swoole,确实支持 enable_static_handler 配置项,但开启后:
- 它只匹配
document_root下的文件,不走路由,也不触发中间件,调试时看似方便,但无法做权限校验、防盗链、AB 测试等业务逻辑 -
sendfile虽快,但没缓存头(Cache-Control、ETag)、不压缩、不支持范围请求(Range),Chrome 开发者工具里看响应头全是缺失的 - PHP 进程常驻内存,每个静态请求都占用一个 worker,高并发下容易挤占动态请求资源
Nginx 配置动静分离:路径匹配比后缀更可靠
别再用 location ~* \.(js|css|png)$ 这种后缀匹配了 —— 容易误伤 API(比如 /api/v1/export.xlsx 被当成静态文件返回 404)。推荐按路径隔离:
- 把所有静态资源统一放在
/static/或/assets/下,前端构建时配置publicPath: '/static/' - Nginx 配置明确限定范围:
location ^~ /static/ { alias /path/to/hyperf/public/; expires 1y; add_header Cache-Control "public, immutable"; gzip on; } - 动态请求全部交给 Hyperf:
location / { proxy_pass http://127.0.0.1:9501; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
Hyperf 静态文件路由必须禁用或重定向
如果 Hyperf 的 Router 里还留着类似 GET /{file}.js 或 GET /public/{path:.+} 这类兜底规则,Nginx 的 location ^~ /static/ 就会失效 —— 请求根本到不了 Nginx,被 PHP 提前截获了。务必检查:
- 删除所有泛匹配静态路由(特别是
GET /{path:.+}) - 确认
config/autoload/middlewares.php中没有对/static/路径启用鉴权中间件 - 开发期可加一条强制跳转(临时):
GET /static/(.*) => redirect to /static/$1
,避免本地调试时路径错乱
真实部署时,document_root 和 alias 别混用
Nginx 的 root 和 alias 行为完全不同,配错会导致 404:
-
root /var/www/hyperf/public;+location /static/→ 实际查找路径是/var/www/hyperf/public/static/xxx.js(多了一层/static) -
alias /var/www/hyperf/public/;+location ^~ /static/→ 实际查找路径是/var/www/hyperf/public/xxx.js(/static/被剥离) - Hyperf 构建产物默认在
public/目录,所以必须用alias,且结尾带斜杠;root适合整个站点根目录就是静态资源目录的场景
最易忽略的一点:Nginx 的 alias 后路径末尾斜杠不能省,少一个就会导致文件路径拼接错误,而且错误不报日志,只返回 404 —— 检查时先 curl -I http://localhost/static/app.js 看状态码和 Content-Type,再翻 error.log 里的 “open() failed” 行。











