单页应用刷新 404:try_files 一行解决
发布时间:2026-03-19 08:27       
更新时间:2026-03-19 23:47
单页应用(SPA)首页正常、刷新或直连子页面就 404,原因是 history 路由把 /user/profile 这类路径交给前端 JS 处理,服务器上并没有这个文件或目录,Nginx 老老实实返回 404。解法是把这类路径统一兜回 index.html,一个 location 块就能全部接住。顺带说明:用 # 号的 hash 路由不受影响,# 后面的部分根本不会发给服务器,用 hash 路由的项目碰不到这个坑。
try_files 怎么写
location / {
try_files $uri $uri/ /index.html;
}
含义是:先找同名文件,再找同名目录,都没有就返回 /index.html 的内容。前端路由拿到页面后按 URL 渲染对应组件,用户看到的仍是正确的子页面,刷新、分享链接、直接输入地址都不会再 404。$uri/ 这一段对有真实目录的场景有用,没有的话留着也无害,写全些免得真有目录结构的页面时再改。
子路径与多应用共存
一个域名下挂多个前端应用时,按前缀分段:
location /app/ {
try_files $uri $uri/ /app/index.html;
}
location /admin/ {
try_files $uri $uri/ /admin/index.html;
}
各自的 index.html 路径要写全,构建时 base 对应设成 /app/、/admin/,两边对齐才不会互相串资源,一个应用引用到另一个的文件,症状是样式错乱。要留意带 hash 资源的 location 正则别把子应用目录漏掉或误匹配,配完拿两个应用各自的资源 URL 实测一遍。
一个副作用要知道
兜底之后,服务器不再对 SPA 路径报 404——用户输错的不存在路由,返回的也是 index.html 加 200。真正的"页面不存在"要在前端路由里配 NotFound 组件处理。调试服务器静态文件问题时也要记得这一点:文件确实不存在时,先确认是不是 try_files 把请求兜走了,别被 200 响应迷惑。index.html 本身记得配 no-cache,否则兜回的可能一直是旧版本页面。
部署之外的一句话
try_files 解决的是部署层的问题。SPA 的内容全靠浏览器端 JS 渲染,搜索引擎抓取效果天然吃亏,对收录有要求的业务站点,根治要靠预渲染或服务端渲染方案,那属于架构选型,不是一行配置能覆盖的,按预算和维护能力权衡后再定。