Vue路由包含#号导致的Nginx无法转发问题

要解决的场景

现有2个前端应用A和B,域名不同,页面相同(B对A进行了重构),后续页面功能的开发都会在B应用中,但由于A应用页面的入口已经对外开放,故不能A应用不能下线,期望通过跳转的方式,将所有打到A应用的请求,转发到B应用上。

部署情况

A应用为纯VUE静态工程,使用Nginx进行负载,URL采用Hash模式,即采用#方式,比如https://xxx.xx.com/myreport/#/myReport/tijian?ad_od=1,https://xxx.xx.com/myreport/#/myReport/jiyin?ad_od=1

B应用为React静态工程,使用Nginx进行负载

方案一:通过A应用的Nginx进行连接的跳转

优点:A应用的不需要任何开发量,代码不需改动,在Nginx上做层转发就行。
实现方式:涉及到A的3个页面需要跳转,分别对应3个路径,
https://xxx.xx.com/myreport/#/geneIndex?ad_od=1
https://xxx.xx.com/myreport/#/myReport/tijian?ad_od=1
https://xxx.xx.com/myreport/#/myReport/jiyin?ad_od=1
,配置Nginx的location正则匹配A的路径,将对应转发到B应用页面,配置后如下
Vue路由包含#号导致的Nginx无法转发问题_第1张图片存在的问题:Nginx接收到的URL全为https://xxx.xx.com/myreport,拿不到#之后的路径,所以无法进行页面跳转。Nginx日志如下:
Vue路由包含#号导致的Nginx无法转发问题_第2张图片

具体原因井号#是指导浏览器动作的,为浏览器行为,比如用来页面定位,对服务端完全无用,故#号之后的内容是不会发送到服务端的,所以Nginx也就无法转发
可以看下https://xxx.xx.com/myreport/#/myReport/jiyin?ad_od=1请求的具体内容。
Vue路由包含#号导致的Nginx无法转发问题_第3张图片
参考文档:#号的用法
结论:通过Nginx跳转的方式,行不通

方案二、将A应用的路由router改为history方式,去除#号,再进行Nginx跳转

实现方式
第一步:设置vue的路由模式

const router = new VueRouter({
 mode: 'history',
 routes: [...]
})

第二步:设置Nginx配置

# 注释内容为默认配置,即不需要进行跳转B应用
#location / {
# try_files $uri $uri/ /index.html;
#}
# 正则匹配页面,然后跳转B应用对应页面
location ~* /myreport {
       if ($uri ~* /myreport(\.*)geneIndex) {
           rewrite ^/(.*)$ https://xxx.xx.com/examreport/#/ last;
       }
       if ($uri ~* /myreport(\.*)tijian) {
           rewrite ^/(.*)$ https://xxx.xx.com/examreport/#/MyreportFortijian?tabtype=1 redirect;
       }
       if ($uri ~* /myreport(\.*)jiyin) {
           rewrite ^/(.*)$ https://xxx.xx.com/examreport/#/Myreport?tabtype=2 permanent;
       }
   }

参考官网解决方案
结论:这种方式技术上行得通,移除#后可以通过Nginx进行负载均衡,这样的VUE和Nginx更搭配,但由于A应用的链接已经对外发布,调整路由模式后,之前带#号的地址再去访问,就会提示404,所以针对要解决的场景而言,这种方案同样行不通。

方案三、通过A应用进行跳转

具体实现:Nginx不做任何转发,直接透传给Vue静态应用,然后应用内部不再向后端发起ajax请求,而是直接重定向到B应用的页面。
由于涉及到多个页面,每个页面里头重定向会比较繁琐,可以直接在路由router.js中配置拦截器,匹配路径统一转发,类似:

router.beforeEach((to, from, next) => {
  
    //此处判断路径,直接重定向
    
})

结论:每1个请求实际都发起了2次HTTP请求,用户体验较差,并且A应用的代码逻辑也需要调整,但目前这是唯一能处理这种场景的方案。

你可能感兴趣的:(前端,vue,nginx)