记录一个Chrome
的特性引发的问题。
背景
前些日子有一个同事找我,说是页面上出现了非常奇怪的跳转现象。
简单来说就是,他做了一个前置页面A
,用于获取用户登录信息,根据用户角色的不同,自动跳转至不同路由的页面。但是当他点击浏览器后退时,返回的不是页面A
,而是空白的新标签页。相当于页面A
的历史记录被浏览器吃掉了,所以直接后退到了新标签页。
我之前遇到过浏览器导航后退出现了非预期的情况,但只是出现在UC浏览器,并且是在 pathname 路由的模式下。但同事给我发的视频中,使用的是Chrome
,且用的 hash 路由。之前的经验让我第一时间联想到,是不是Chrome
出现新bug了?
测试
我写了一个简单的可复现用例
/
// PageA.tsximportReact, { useEffect } from'react'; import { history } from'umi'; constPageA= () => { useEffect(() => { setTimeout(() => { history.push('/sub-page/1'); // window.history.pushState(null, '', '/sub-page/1');// location.href = '/sub-page/1'; }, 1000); }, []); return ( <div> This is Page A. </div> ); }; exportdefaultPageA;
然后我得到了这样一个稳定的现象,页面A
在1秒后跳转至页面B
,但点击后退按钮时,并不能回退到页面A
,且不论是使用react
御用的 history
或原生history
或是直接修改location
,都能稳定复现这个情况。
然后我也发现了能够避免吃掉历史记录的方式,就是用户与页面产生交互,比如这样点击一下页面,前进后退就正常了:
emmm?“用户交互后才生效”这个操作怎么和之前 Chrome 提出的,禁止在用户与页面交互前自动播放有声视频的安全策略如出一辙?我隐约感觉到这可能不是bug
排查
由于我先入为主的观点,我还是以为这是Chrome
的缺陷,也就是我认为,在用户与页面交互之前,浏览器遗漏了历史记录,所以我在chromium
的issue
看板上搜了好一会儿,但是并没有得到我想要的结果。
我不死心,拉了历史版本的Chromium
挨个测试,最后发现在74版本的Chromium
上,出现了这个特性。这个版本距离现在已经两年了吧,这么明显的问题不可能没有人提出吧?
于是我开始往浏览器新特性的方向去查找,查了74版本相关的New in Chrome
,但似乎没有找到太多内容。
就在这时,同事给我发来了一个链接,这里说明了在用户与页面交互之前,Chrome
的前进后退按钮会忽略该网站所跳转过的历史记录栈。
这个操作是为了防止网站恶意拦截用户的浏览器导航而做的。例如该网站通过在页面A
进入页面后立即push
跳转到新页面的代码,导致你后退时便触发该跳转,而永远无法后退到更早的页面。
后来我也找到了相关的文章,看来之前的方向不太对。
结语
由于存在这个特性,作为前端工程师的我们,在页面跳转时就要尽量避免这种,进入页面后直接跳转页面,且还需要用户进行后退操作的业务逻辑。
另外时间关系,我只搜索到了上面两个博主发的介绍文章,如果有官方对于该特性的文档,欢迎告知。