你的网站链接为什么又长又丑,还影响收录?

“这链接怎么长得跟密码一样?”
——上周帮朋友看站,他指着 product.php?id=872&ref=utm&utm_source=weibo 这串问我。我点点头:不是你代码写得差,是伪静态还没动。

这种带问号、参数堆成山的链接,用户懒得点,搜索引擎也懒得爬。它不报错,但就像给网站穿了双不合脚的鞋——走不远,还容易崴脚。

伪静态到底是什么?和真静态有什么区别?

真静态,就是实实在在存着的一个 .html 文件。你访问它,Nginx 找到就发,快得像开冰箱拿瓶水。

伪静态呢?是“演”出来的静态。背后还是 PHP 或 Python 在跑,数据库照查,但 URL 被 Nginx 悄悄“换脸”了:把 /article.php?id=123 变成 /article/123.html。浏览器地址栏干净了,搜索引擎也当它是正经目录。

我上个月接手一个本地资讯站,原来全是 news.php?cat=5&id=789 这种链接。改完伪静态,用 /news/5/789.html 的形式上线后,站长说蜘蛛抓得勤了,新内容进收录的速度明显提升——不用等三四天,当天下午就能搜到。

为什么一定要在Nginx里设置伪静态?

程序里也能设路由,比如 WordPress 插件点几下就搞定。但它是在 PHP 层做的:请求先到 Nginx,再转给 PHP,PHP 解析完才决定跳哪儿。多绕一圈,服务器多喘一次。

Nginx 伪静态是“拦路改单”:请求刚进门,还没见着 PHP,就被它按规则重写好了,直接转发。相当于快递员在分拣中心就贴好新面单,省得送到楼下了再让住户自己手写一张。

更实在的是,它不挑框架。你今天用 ThinkPHP,明天换成 Laravel,只要 Nginx 配置不动,URL 规则就稳如老狗。换程序不等于换链接,用户收藏的页面不会突然 404。

Nginx伪静态的核心:location与rewrite指令怎么用?

核心就两件事:匹配路径 + 改写路径。全靠 locationrewrite 配合。

location 是守门员,负责判断“这个请求该不该归我管”。比如 location /article/ { ... } 就只管以 /article/ 开头的请求。

rewrite 是剪刀手,在匹配成功后,把 URL 剪一刀、贴一贴,变成你要的样子。语法很简单:

rewrite ^/article/([0-9]+)\.html$ /?p=$1 last;

拆开看:

  • ^/article/([0-9]+)\.html$ 是正则,匹配 /article/123.html 这种格式
  • /?p=$1 是目标,$1 指代括号里捕获的数字(比如 123)
  • last 是指令:改完后,拿着新地址重新进 server 块找一遍 location

别怕正则,先记住 ^ 是开头、$ 是结尾、([0-9]+) 是一串数字、\. 是真正的英文句点——够你起步了。

5个最常见的伪静态规则实战写法

别背理论,直接抄作业。下面都是真实项目里反复验证过的写法,粘过去改改就能用。

1. 基础文章页重写
场景:WordPress 默认链接 /?p=123 → 改成 /article/123.html

location / {
    rewrite ^/article/([0-9]+)\.html$ /?p=$1 last;
}

用户点 /article/123.html,Nginx 内部悄悄调用 /?p=123,页面照常加载,URL 看着像静态。

2. 分类页与分页重写
场景:/?cat=news&page=2 → 改成 /news/2/

location / {
    rewrite ^/([a-z]+)/([0-9]+)/$ /?cat=$1&page=$2 last;
}

注意:([a-z]+) 匹配纯字母分类名(如 news、tech),([0-9]+) 匹配页码。斜杠 / 写在正则末尾,确保 /news/2//news/2 不被混为一谈。

3. 去掉URL中的index.php
场景:ThinkPHP/Laravel 默认带 /index.php/home/article → 改成 /home/article

location / {
    if (!-e $request_filename) {
        rewrite ^/(.*)$ /index.php/$1 last;
    }
}

逻辑很直白:如果请求的文件或目录不存在(比如不是图片、不是 CSS),就甩给 index.php 处理。

4. 旧链接301跳转到新规则
场景:老商品页 /show.php?id=100 已被收录,必须跳转到 /product/100.html

location = /show.php {
    if ($arg_id ~ "^[0-9]+$") {
        return 301 /product/$arg_id.html;
    }
}

这里用了 location = /show.php 精确匹配,避免误伤;return 301rewrite ... permanent 更轻量,也更安全。

5. 复杂商城SKU规则
场景:/goods.php?id=100&color=red&size=m → 改成 /goods/100-red-m.html

location /goods/ {
    rewrite ^/goods/([0-9]+)-([a-z]+)-([a-z]+)\.html$ /goods.php?id=$1&color=$2&size=$3 last;
}

三个小括号,分别捕获 ID、颜色、尺码。命名越贴近业务,后期维护越不懵。

写规则时,你90%会踩的这些坑怎么避免?

我见过太多人改完配置,一重启,首页白屏、图片全红叉、后台登录页都打不开。不是 Nginx 坏了,是规则写“飘”了。

1. 死循环:自己绕着自己转
典型症状:Nginx 报错 rewrite or internal redirection cycle
原因:rewrite 后的新地址又被同一条规则匹配,反复重写。
解法:加 lastbreak 终止链路;或者把重写目标设计成不再匹配原规则的形式(比如加 .html 后缀,而原规则不匹配带后缀的路径)。

2. location 顺序错乱,规则压根不执行
Nginx 不是“从上往下读”,而是按匹配优先级来:

  • location = /exact(完全相等)最高
  • location ^~ /static(前缀匹配,且不走正则)次之
  • location ~ \.php$(正则匹配)再次
  • location /(通用前缀)垫底
    所以,别把 rewrite 塞进 location ~ \.php$ 里——PHP 请求根本不会进那里。通用规则,一律放 location / { ... }

3. 正则太野,把不该动的也改了
比如用 (.*) 匹配所有,结果连 /favicon.ico 都被重写,返回 404。
建议:能用 ^/article/([0-9]+)\.html$ 就别用 ^/.*\.html$;测试时多试几个边缘情况:带斜杠/不带斜杠、大小写、中文参数(如果业务需要)。

4. 忘了放行静态资源,全站变“裸奔”
location / { rewrite ... } 会吃掉所有请求,包括 /css/app.css。结果 CSS 加载失败,页面惨白。
必须在伪静态规则前,单独加一段静态文件放行:

location ~* \.(gif|jpg|jpeg|png|css|js|ico|woff2|ttf)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

这段放在 location / { ... } 上面,Nginx 就会优先处理这些后缀,不往下走了。

写完规则,怎么测试和调试才安全?

别信“应该没问题”,线上环境没有“应该”。

第一步:在本地用 Docker 或虚拟机搭个最小 Nginx+PHP 环境,把线上配置复制过去,只改域名和路径。
第二步:改完配置,终端敲 nginx -t。看到 syntax is oktest is successful 才算过关。
第三步:nginx -s reload 重载,立刻打开浏览器,测三件事:

  • 新链接(如 /article/123.html)能不能打开
  • 旧链接(如 /?p=123)会不会 404(应该 404,说明新规则生效了)
  • 图片、CSS、JS 是否正常加载(右键检查元素,看 Network 标签页)
    第四步:盯住日志。执行 tail -f /var/log/nginx/error.log,一边点页面一边看输出。任何 rewrite 相关报错,都会在这里冒出来,比猜强一百倍。

今天下班前,用这3步搞定你的第一个伪静态规则

别收藏吃灰,现在就打开终端:

  1. 找到你的配置文件:SSH 登录服务器,运行 ls /etc/nginx/conf.d/*.confls /etc/nginx/sites-available/,找到你网站对应的 .conf 文件(比如 myblog.conf)。
  2. 加一条最简规则:用 nanovim 打开它,在 server { ... } 块里找到 location / { 这一行,在花括号内第一行,粘贴这条 WordPress 通用规则:
    rewrite ^/([0-9]+)/?$ /?p=$1 last;
    
    保存退出,立刻执行 nginx -t 确认语法。
  3. 平滑上线并验证:运行 nginx -s reload,然后打开浏览器,访问你博客任意一篇文章的原始链接(如 https://your-site.com/?p=123),手动在地址栏改成 https://your-site.com/123/ —— 如果页面正常打开,恭喜,你的第一个伪静态规则已跑通。

就这一条,够你今晚睡踏实。剩下的,不过是把 123 换成 article/123.html,把 p= 换成 cat=…… 一步步来,URL 就会越来越像人写的。