記錄一個 Chrome
的特性引發的問題。
背景
前些日子有一個同僚找我,說是頁面上出現了非常奇怪的跳轉現象。
簡單來說就是,他做了一個前置
頁面A
,用于擷取使用者登入資訊,根據使用者角色的不同,自動跳轉至不同路由的頁面。但是當他點選浏覽器後退時,傳回的不是
頁面A
,而是空白的新标簽頁。相當于
頁面A
的曆史記錄被浏覽器吃掉了,是以直接後退到了新标簽頁。
我之前遇到過浏覽器導航後退出現了非預期的情況,但隻是出現在UC浏覽器,并且是在 pathname 路由的模式下。但同僚給我發的視訊中,使用的是
Chrome
,且用的 hash 路由。之前的經驗讓我第一時間聯想到,是不是
Chrome
出現新bug了?
測試
我寫了一個簡單的可複現用例
// PageA.tsx
import React, { useEffect } from 'react';
import { history } from 'umi';
const PageA = () => {
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>
);
};
export default PageA;
然後我得到了這樣一個穩定的現象,
頁面A
在1秒後跳轉至
頁面B
,但點選後退按鈕時,并不能回退到
頁面A
,且不論是使用
react
禦用的
history
或原生
history
或是直接修改
location
,都能穩定複現這個情況。

然後我也發現了能夠避免吃掉曆史記錄的方式,就是使用者與頁面産生互動,比如這樣點選一下頁面,前進後退就正常了:
emmm?“使用者互動後才生效”這個操作怎麼和之前 Chrome 提出的,禁止在使用者與頁面互動前自動播放有聲視訊的安全政策如出一轍?我隐約感覺到這可能不是bug
排查
由于我先入為主的觀點,我還是以為這是
Chrome
的缺陷,也就是我認為,在使用者與頁面互動之前,浏覽器遺漏了曆史記錄,是以我在
chromium
的
issue
看闆上搜了好一會兒,但是并沒有得到我想要的結果。
我不死心,拉了曆史版本的
Chromium
挨個測試,最後發現在74版本的
Chromium
上,出現了這個特性。這個版本距離現在已經兩年了吧,這麼明顯的問題不可能沒有人提出吧?
于是我開始往浏覽器新特性的方向去查找,查了74版本相關的
New in Chrome
,但似乎沒有找到太多内容。
就在這時,同僚給我發來了一個
連結,這裡說明了在使用者與頁面互動之前,
Chrome
的前進後退按鈕會忽略該網站所跳轉過的曆史記錄棧。
這個操作是為了防止網站惡意攔截使用者的浏覽器導航而做的。例如該網站通過在
頁面A
進入頁面後立即
push
跳轉到新頁面的代碼,導緻你後退時便觸發該跳轉,而永遠無法後退到更早的頁面。
後來我也找到了相關的
文章,看來之前的方向不太對。
結語
由于存在這個特性,作為前端工程師的我們,在頁面跳轉時就要盡量避免這種,進入頁面後直接跳轉頁面,且還需要使用者進行後退操作的業務邏輯。
另外時間關系,我隻搜尋到了上面兩個部落客發的介紹文章,如果有官方對于該特性的文檔,歡迎告知。