先给结论:静态响应与脚本渲染结果不同,通常意味着你看到的“404页面”由两层拼成——服务器返回的状态码和初始HTML,以及浏览器执行脚本后替换出的界面。定位差异的关键不是继续改页面文案,而是把两层分开抓取、分开比对,确认差异发生在响应头、初始HTML还是脚本执行之后。若两层都返回404但内容不同,优先保留服务器层;若服务器层正确、脚本层错误,再决定改写脚本或退出脚本渲染方案。
静态响应指服务器直接返回的响应头与初始HTML,脚本渲染指浏览器执行JavaScript后生成的DOM。对自定义404错误页来说,前者决定状态码是否为404、是否带正确的缓存与内容类型,后者决定用户最终看到什么。很多排查失败,是因为只看了浏览器开发者工具里的最终DOM,没有看禁用脚本后的初始HTML,也没有单独请求一次原始响应。
一个可执行动作:用命令行工具只取响应头和初始正文,例如 curl -I 目标地址 与 curl 目标地址,再与浏览器禁用脚本后的结果对照。若命令行返回404、初始HTML含错误提示,而浏览器最终显示正常内容,差异就落在脚本层,下一步应查脚本是否在404状态下仍执行了重定向或内容替换。
这种情况最常见。服务器已返回404和一份可读的初始HTML,脚本却在执行后把内容替换成另一套界面,甚至把状态码感知逻辑覆盖掉。此时有两种成立条件不同的选择。
动作与结果:先禁用脚本请求一次,记录初始HTML是否含错误说明。若含,保留脚本作为增强;若不含,改写脚本或退回服务端渲染。这个结果直接决定下一步是调脚本逻辑,还是回到服务器模板。
如果原始请求返回的就不是404,或返回404但正文为空,问题不在脚本。常见原因是路由把未知路径交给了首页模板、重写规则把请求导向了其他状态,或缓存层返回了旧响应。此时应逐项核对:状态码、Content-Type、缓存相关头、以及正文长度。
假设一个场景:同一路径在带查询参数时返回404,去掉参数后返回200。这并不证明脚本有问题,也可能是路由匹配或缓存键规则不同。合理做法是固定变量,分别请求带参数与不带参数的版本,比较响应头差异。若差异只在缓存头,下一步应查缓存规则;若差异在状态码,下一步应查路由与重写配置。
脚本层差异可能来自异步请求失败、条件判断依赖了错误的状态码、或渲染时机早于数据返回。可用以下证据区分:
这些现象只能说明差异位置,不能单独证明某次修改正确。例如脚本请求返回200,不等于404处理逻辑正确,也可能只是接口默认返回了成功包装。
三种方向各有前提。保留适用于脚本只做渐进增强、初始HTML已完整;改写适用于脚本必要但可调整执行顺序与状态判断;退出脚本渲染适用于错误页必须稳定、快速、可被各类客户端读取,且脚本带来的收益不足以抵消不确定性。退出不等于删除脚本,而是让服务器输出完整错误页,脚本仅在可用时增强。
动作与结果:若选择退出,先把服务器模板补全为可独立阅读的404页,再移除脚本对错误内容的强制替换。之后重新比对静态响应与浏览器结果,若两者一致,说明差异已收敛;若仍不同,应回到响应头与缓存层继续查,而不是再改文案。