页面打不开不是 Nginx 的错

SSL 证书签发成功,伪静态规则配置完成,运行目录指向了 public。但是页面就是打不开。

顺手拿 http:// 开头的地址试一下,它很配合地 301 跳到了 https://。

到这儿我以为部署完了。然后去访问接口地址------页面打不开。

没有 502,没有 404 页面,没有 PHP 报错。浏览器上就是一片空白,或者一句「无法访问此网站」。

这时候最常见的反应是回去翻 Nginx 配置:是不是 location 写错了?伪静态规则不对?server_name 没匹配上?

都不是。

这批机器是 1Panel + OpenResty + PHP 容器,站点跑的是 ThinkPHP 8,刚做完首次部署的验收。

关键在于问一句:刚才那个 301 跳转,是谁干的。

是 Nginx,在这儿就是 OpenResty。它要干成这件事,得同时满足 3 条:进程在监听 80 端口;server_name 匹配上了这个域名;跳转规则不管是 return 301 还是 rewrite,被正确执行。

3 条全成立,跳转才会成功。

所以跳转成功这件事本身就是一份体检报告。没监听、端口没放行,表现是连接被拒绝或者超时。证书有问题,表现是证书错误、UNABLE_TO_VERIFY_LEAF_SIGNATURE。后端 PHP 挂了但 Nginx 正常,表现是能连上、能跳转,但页面空白或 5xx。

第三种就是当时的情况。问题一定在跳转之后的处理环节,也就是 PHP。

这个判断把排查范围从整个 Web 栈直接压到了 PHP 应用,省掉大量瞎猜。

往下一层,看入口文件。PHP 站点的入口通常是 public/index.php,而这个文件的第一行有效代码几乎都是同一句:

php 复制代码
require __DIR__ . '/../vendor/autoload.php';

vendor/ 不存在,这一行就让 PHP 进程直接崩。

注意严重程度:这不是某个函数调用失败,也不是某个页面返回错误,这是加载阶段的 Fatal error。

区别在于:框架已经跑起来、只是路由匹配不上,你会看到一个 404 页面,甚至是框架自带样式的错误页;vendor 缺失,框架根本没被加载,连优雅地报一个错的能力都没有。

所以最后看到的是「页面打不开」,而不是 404。它连 404 都渲染不出来。

vendor/ 为什么永远不会自己出现,这才是这篇真正值得记的地方。

两件事叠在一起。一是 .gitignore 里写了 /vendor,git clone 下来的仓库天然不含 vendor/,这是 PHP 项目的通行做法,依赖不进版本库。二是部署脚本的 rsync 排除清单里也写了 vendor/,这一条本身正确且必要,否则每次更新代码都会把服务器上装好的依赖删光。

两条都没错。于是结果就是这个站点目录里不会有 vendor/,而且永远不会自己出现。

那它从哪来?只能原地装。

bash 复制代码
composer install --no-dev

仓库里带了 composer.lock 的话,这一步就是可复现的------严格按锁定版本安装,不随服务器 PHP 版本浮动。所以 composer.lock 务必纳入版本控制。

症结在于:排除清单和启动必需件,是同一批文件。

rsync 要排除 .env、vendor/、runtime/,理由是它们不是代码、不该被同步覆盖。可它们又都是必须存在的东西。

排除不等于不需要,只是不由同步来负责。

部署流程如果只写了排除什么,却没写排除之后由谁生成,就一定会漏,而且漏得毫无察觉:rsync 不回显任何异常,目录列表看起来完全正常,直到你去访问站点。

装完依赖再访问,页面有反应了。错误换了个样子。

第 2 层:.env 也不在。

它和 vendor/ 是同一个原因:.gitignore 忽略了它,rsync 排除清单里也有它。所以数据库配置、密钥全是空的。表现出来是能访问了,但数据库连不上。

第 3 层:请求的地址本身可能就是错的。

这层最容易被忽略,因为前两层修好之后,报错信息会突然变得很像业务问题。当时访问的是 /api/index/ping,回显四个字:方法不存在。

这条回显含金量很高。它证明框架已经完全跑起来了,能实例化控制器、能查路由表,只是路由表里没有这一条。

所以它恰好出现在前两层修好之后、第 3 层修好之前,把三层问题的修复时序直接打了出来。

去路由文件里核对,这个动作确实存在,只是注册在另一个分组下:

bash 复制代码
实际访问:  /api/index/ping
正确地址:  /api/auth/ping

改对地址,接口回 pong。从「打不开」到「方法不存在」再到「pong」,报错是一条收敛路径------前两层没修好之前,第 3 层根本不会暴露。

相关推荐
itmigrate7 小时前
前端项目里,Object.is 并不是 === 的平替
前端
喵了几个咪7 小时前
GoWind CMS 拆解:在 Go 里给 TipTap 搭一套 Yjs 协同后端
开发语言·后端·golang
Flynt7 小时前
我把微信运动的排行榜和定点推送复刻了一遍:100万次步数更新只要4秒,坑在别处
redis·后端·性能优化
小大宇8 小时前
Vue知识点6-computed计算属性
前端·javascript·vue.js
程序员海军8 小时前
尤雨溪 : Vue 4 已经在规划中了!
前端·javascript·vue.js
2601_949970698 小时前
HumanizeDuration 跨端三方库仓颉适配全流程
前端·javascript·flutter
_孤傲_9 小时前
快速掌握 MySQL 语法
数据库·后端·mysql
风骏时光牛马10 小时前
后端服务接口开发与性能优化
前端
kyriewen10 小时前
我让 4 个 AI 互相 review 代码,最温柔的那个下手最狠
前端·程序员·ai编程
计算机魔术师11 小时前
493家公司白砸AI钱?Apollo这组数据戳破了幻觉
前端