一個來自create-react-app腳手架警告的思考

最近在開發一個react項目,項目是用create-react-app腳手架建立的,當我在個人項目的菜單欄中添加了一個打開一個外鏈的a標籤時,我收到了一個來自create-react-app的警告信息,信息內容以下

<img alt="opener警告" src="http://198.252.107.180/~gongm...; width="100%"/>html

意思就是說「在沒有rel="noopener noreferrer"屬性的a標籤中使用target="_blank"存在必定的風險」react

這個提示瞬間把我吸引了,之前關於a標籤收到的提示都是沒有設置alt屬性啊什麼的,可是也只是提示我說爲了顯示的友好什麼的,此次居然提示我有風險,面對這種問題,必須一探究竟啊。git

查閱了一些資料獲得了以下關於a標籤一個介紹github

當一個外部連接使用了target=_blank的方式,這個外部連接會打開一個新的瀏覽器tab。此時,新頁面會打開,而且和原始頁面佔用同一個進程。這也意味着,若是這個新頁面有任何性能上的問題,好比有一個很高的加載時間,這也將會影響到原始頁面的表現。若是你打開的是一個同域的頁面,那麼你將能夠在新頁面訪問到原始頁面的全部內容,包括document對象(window.opener.document)。若是你打開的是一個跨域的頁面,你雖然沒法訪問到document,可是你依然能夠訪問到location對象。

不看不知道一看嚇一跳有木有。主要是兩個點是我之前從未在乎的跨域

  1. 用target="_blank"方式打開的tab和原始頁面佔用同一個進程(UI進程)
  2. 新打開的頁面能獲取到原始頁面的document。

第一個問題不用我說都知道是很是須要注意的,新的頁面中的全部行爲都會間接影響到原始頁面的性能。瀏覽器

這裏主要研究第二個問題。爲此,我作了小小的實驗。app

opener測試

上圖解釋:oop

  • 首先打開了第一個頁面,第一個頁面只有一個「打開一個新頁面」的a標籤
  • 點擊這個連接,打開了一個新頁面。新頁面中有一個按鈕,「告訴打開個人那個頁面,我喜歡林志玲」。
  • 點擊新頁面的按鈕而後回到第一個頁面,發現第一個頁面多出來了一排紅色的文字「我喜歡林志玲」。
  • 停在第一個頁面5s鍾,第一個頁面自動跳轉到了百度首頁。

上面兩個頁面的代碼分別以下:性能

opener-test.html測試

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
        <a target="_blank" href="test-opener-2.html">打開一個新頁面</a>
    </body>
</html>

opener-test-2.html

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
        <h1>我是新打開的頁面</h1>
        <button type="button" id="btn">告訴打開個人那個頁面,我喜歡林志玲</button>
        <script>
            document.getElementById('btn').addEventListener('click', function() {
                var _opener = window.opener;
                var p = _opener.document.createElement('p');
                p.innerHTML = "我喜歡林志玲";
                p.style.color = "#f33";
                _opener.document.body.appendChild(p);
                setTimeout(function() {
                    _opener.location.href = "//www.baidu.com";
                }, 5000)
            });
        </script>
    </body>
</html>

新的頁面不只往原始頁面添加了一段話,並且還讓他離開了原來的頁面。

注:在上面的例子中,兩個頁面位於同一個域下面,若是兩個頁面位於不一樣的域,那上面的第一個效果就是不行的,由於不一樣域的狀況下,新頁面拿不到opener對象的document,可是location對象是能夠拿到的,因此第二個效果任然有效。

怎麼禁止上面的行爲呢?按照create-react-app的提示信息,給鏈接加上rel屬性,以下:

<a rel="noopener noreferrer" target="_blank" href="https://marvengong.github.io/fastmock-docs/book/">

上面的rel屬性值多了一個noreferrer它的做用和noopener是同樣的,只是適用於低版本的瀏覽器。

這樣處理後,新打開的頁面的window對象上就沒有opener和referrer對象了。

相關文章
相關標籤/搜索