背景
项目中需要将短链接 https://v3.abc.com/23-DLN25D 解析到 Vue 前端页面,并传递 mid=23、code=DLN25D 两个参数。
Vue 项目使用 history 路由模式,入口文件为 redpack.html。
Nginx 配置
bash
location ~* ^/([0-9]+)-([A-Za-z0-9]+)$ {
rewrite ^/([0-9]+)-([A-Za-z0-9]+)$ /redpack.html?mid=$1&code=$2 last;
}
location / {
try_files $uri $uri/ /redpack.html;
}
问题现象
用 last 时,访问 https://v3.abc.com/23-DLN25D:
curl -I返回 HTTP 200,内容是redpack.html(728字节),说明文件确实返回了- 但浏览器页面空白,Vue 组件的
created不执行,没有任何反应
直接访问 https://v3.abc.com/redpack.html?mid=23&code=DLN25D 却完全正常。
原因分析
last |
redirect(302) |
|
|---|---|---|
| 处理方式 | Nginx 内部重定向 | 返回 302,浏览器重新发请求 |
| 浏览器地址栏 | 不变,仍是 /23-DLN25D |
变为 /redpack.html?mid=23&code=DLN25D |
| Vue Router 看到的 path | /23-DLN25D |
/redpack.html |
| 路由是否匹配 | 未匹配,组件不加载 | 匹配 ScanEntry,组件正常加载 |
last 是 Nginx 内部完成整个处理,浏览器完全不知道发生了重写,地址栏 path 仍是 /23-DLN25D。Vue Router history 模式拿到这个 path,路由表里找不到对应规则,组件不挂载,created 自然不执行。
redirect 让浏览器收到 302 后真正跳转 到新 URL,地址栏变化,Vue Router 拿到正确的 /redpack.html 路径,路由匹配成功,一切正常。
解决方案
把 last 改为 redirect:
bash
location ~* ^/([0-9]+)-([A-Za-z0-9]+)$ {
rewrite ^/([0-9]+)-([A-Za-z0-9]+)$ /redpack.html?mid=$1&code=$2 redirect;
}
location / {
try_files $uri $uri/ /redpack.html;
}
总结
当 Vue history 模式的路由需要依赖 URL path 匹配时,Nginx rewrite 必须用
redirect或permanent,而不能用last。last只适合纯后端处理的场景,前端路由感知不到内部重写。