你的网站链接为什么又长又丑,还影响收录?
“这链接怎么长得跟密码一样?”
——上周帮朋友看站,他指着 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指令怎么用?
核心就两件事:匹配路径 + 改写路径。全靠 location 和 rewrite 配合。
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 301 比 rewrite ... 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 后的新地址又被同一条规则匹配,反复重写。
解法:加 last 或 break 终止链路;或者把重写目标设计成不再匹配原规则的形式(比如加 .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 ok 和 test is successful 才算过关。
第三步:nginx -s reload 重载,立刻打开浏览器,测三件事:
- 新链接(如
/article/123.html)能不能打开 - 旧链接(如
/?p=123)会不会 404(应该 404,说明新规则生效了) - 图片、CSS、JS 是否正常加载(右键检查元素,看 Network 标签页)
第四步:盯住日志。执行tail -f /var/log/nginx/error.log,一边点页面一边看输出。任何rewrite相关报错,都会在这里冒出来,比猜强一百倍。
今天下班前,用这3步搞定你的第一个伪静态规则
别收藏吃灰,现在就打开终端:
- 找到你的配置文件:SSH 登录服务器,运行
ls /etc/nginx/conf.d/*.conf或ls /etc/nginx/sites-available/,找到你网站对应的.conf文件(比如myblog.conf)。 - 加一条最简规则:用
nano或vim打开它,在server { ... }块里找到location / {这一行,在花括号内第一行,粘贴这条 WordPress 通用规则:保存退出,立刻执行rewrite ^/([0-9]+)/?$ /?p=$1 last;nginx -t确认语法。 - 平滑上线并验证:运行
nginx -s reload,然后打开浏览器,访问你博客任意一篇文章的原始链接(如https://your-site.com/?p=123),手动在地址栏改成https://your-site.com/123/—— 如果页面正常打开,恭喜,你的第一个伪静态规则已跑通。
就这一条,够你今晚睡踏实。剩下的,不过是把 123 换成 article/123.html,把 p= 换成 cat=…… 一步步来,URL 就会越来越像人写的。