极简工具箱

免费在线工具 · 本地计算 · 无需上传

Nginx 重定向与重写:return、rewrite 与 SPA 回退

改版后旧链接全 404、单页应用刷新就白屏、带不带斜杠出现两份内容——这三类问题都能用几行 Nginx 规则解决。

广告位(百度联盟)

一、优先用 return

return 301 https://www.it586.cn$request_uri;
return 302 /login;
return 404;

return 直接返回状态码或跳转,性能好、语义清晰。能用 return 就不要用 rewrite,后者要跑正则、还要考虑 flag 的作用范围。

二、rewrite 的四个 flag

rewrite ^/old/(.*)$ /new/$1 permanent;
flag行为
last重写后重新匹配 location(最常用)
break重写后停止,在当前 location 继续处理
redirect返回 302
permanent返回 301

last 与 break 的区别很实际:last 会再走一遍 location 匹配,可能命中另一条规则;break 就地处理完。写内部重写时用 last,做 URI 改写后直接给静态文件时用 break。

三、单页应用(SPA)刷新 404

React/Vue 的 /user/123 是前端路由,服务器上并没有这个文件,直接刷新就 404。解决:

location / {
    root /var/www/app;
    try_files $uri $uri/ /index.html;
}

含义:先找真实文件,再找目录,都没有就返回 index.html,由前端路由接管。

注意别把它用在有真实 404 需求的站点上,否则所有错误 URL 都返回 200 首页,形成软 404。

四、旧链接批量 301

改版换路径时,逐条写太麻烦,可以按前缀批量转:

# /blog/xxx → /articles/xxx
rewrite ^/blog/(.*)$ /articles/$1 permanent;

# 老域名整体跳新域名
server {
    listen 80;
    server_name old-domain.com;
    return 301 https://www.it586.cn$request_uri;
}

上线前把常见旧 URL 列出来,用 curl -I 逐个确认返回 301 且 Location 正确。301 会被浏览器强缓存,测错了很难回滚,所以测试阶段先用 302,确认无误再改 301。

五、末尾斜杠统一

# 目录补斜杠(避免相对路径错乱)
if (-d $request_uri) {
    rewrite ^(.*[^/])$ $1/ permanent;
}

if 在 location 里要谨慎使用(有「if is evil」的说法),能用 try_files 或独立 location 解决就别用。更简单的做法是:站内链接统一不带斜杠,或统一带斜杠,从源头避免两套 URL。

六、去掉 index.php

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

这样 /article/1 会交给 index.php 处理,URL 里不再出现 index.php。

七、调试技巧

curl -I https://www.it586.cn/old/path      # 只看响应头
curl -sIL https://a.com/x | grep -E "HTTP/|location"   # 跟踪整条跳转链

-L 跟随跳转,能看到最终落地页和中间每一步。跳转成环(A→B→A)时浏览器报 too many redirects,用 -sIL 一眼就能看出环在哪。

Nginx 侧可以临时打开 rewrite_log on;(需 error_log notice)看规则命中情况,排查完记得关掉。

八、SEO 注意

小结

优先 return;rewrite 的 last 会重新匹配、break 就地处理;SPA 用 try_files ... /index.html;批量迁移用前缀正则 301;测试阶段先用 302。

本文相关工具(本地计算,无需上传)

更多使用教程