1. 程式人生 > >【原創】原來你竟然是這樣的Chrome?!Firefox笑而不語

【原創】原來你竟然是這樣的Chrome?!Firefox笑而不語

書接上文

上一篇文章《【原創】用事實說話,Firefox 的效能是 Chrome 的 2 倍,Edge 的 4 倍,IE11 的 6 倍!》,我們對比了不同瀏覽器下FineUIPro一個頁面的效能,發現Firefox的載入速度最快,而眾望所歸的Chrome卻表現的差強人意,載入速度僅僅是Firefox的一半!

最近我們重新對測試和程式碼進行了優化和整理,有如下三個發現:

1. 測試程式碼將開始時間放在<head>標籤的做法有失偏頗,如下所示:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script>
        var __STARTTIME = new Date();
    </script>
</head>

這會導致所計算的時間包含HTML頁面,CSS檔案和JavaScript檔案的網路傳輸時間,實際上這部分是我們測試案例所不關心的,我們僅關心頁面的渲染速度!

因此,優化後的程式碼將開始時間放到頁面底部,如下所示:

</form>
    <script>
        // 等所有JS資源下載完畢後開始
        var __STARTTIME = new Date();

        // 表格渲染完畢後結束
        function onGridRender() {
            F.ui.Grid1.setTitle('表格(23列,500行,行高不同) - 渲染:' + ((new Date() - __STARTTIME) / 1000).toFixed(2));
        }

    </script>
</body>
</html>

 

2. 前面一篇文章《【原創】這一次,Chrome表現和IE11一樣令人失望,圍觀群眾有:Edge,Firefox》,我們發現Chrome解析如下結構時遇到問題:

2.1 頁面結構如下:

<td class="f-grid-cell">
    <div class="f-grid-cell-inner">楊婷婷</div>
</td>

2.2 頁面樣式包含:

.f-grid-cell {
    overflow: hidden;
}
.f-grid-cell-inner {
    position: relative;
}

這樣的 CSS 設定會導致滾動時頁面出現白屏,並且CPU佔用率飆升。

不僅如此,在去除 td 的 overflow:hidden 樣式後,我們發現 Chrome 下的頁面渲染速度也有明顯的提升,這一點對接下來的Chrome效能提升也很重要!

 

3. FineUIPro 程式碼中有強制 Chrome 重繪的瀏覽器特定程式碼,這也是對 Chrome 之前版本存在滾動條不顯示的應急策略:

function forceChromeRepaint(targetNode) {
    //:: Chrome的BUG(Firefox,IE都沒有此問題)
    //:: http://stackoverflow.com/questions/4394350/chrome-scrollbars-not-disappearing-when-content-is-smaller-than-container?rq=1
    if(F._fjs_isChrome) {
        var overflow = targetNode.css('overflow');
        if(overflow === 'auto' && targetNode._fjs_scrollLeft() == 0 && targetNode._fjs_scrollTop() == 0) {
            targetNode.css('overflow', 'hidden');
            //:: 強制瀏覽器重新繪製
            targetNode[0].scrollWidth;
            targetNode.css('overflow', 'auto');
        }
    }
}

在最新版的Chrome下測試,相應的瀏覽器滾動條不顯示問題已經得到了修正,所以可以把相關的強制重繪程式碼去掉了(之前出問題的好像是Chrome v58前後的一些版本,現在Chrome都升級到75了)。這也進一步提升了頁面的渲染速度。

 

經過上面三方面的改進,我們再來看下不同瀏覽器下的頁面渲染效能的對比資料。

優化後的對比資料

和第一篇文章的測試類似,我們將表格行增加到 500 多行,列增加到 20 多列,並且行高不固定,來測試下各個瀏覽器的效能。

測試使用的電腦是 MacBook Pro 筆記本(英特爾 i7-8750H,32GB記憶體,512GB SSD),單獨拆分出一個新的 256GB 分割槽用來安裝 Windows 10 Pro(64位)系統,並更新至最新補丁。

參與測試的瀏覽器都是最新版,分別為:

  • Chrome 75
  • Firefox 68 
  • Edge 44

由於 IE11 有明顯的卡頓,進行本測試意義不大,所以這次不再對 IE11 進行測試。

 

下面是測試結果(第一張是 FineUIPro v5.5.0 的截圖,第二張是程式碼優化後的截圖):

Firefox:

 

 

Chrome:

 

Edge:

 

下面對上述結果進行一個綜述:

瀏覽器 原始的渲染時間(秒) 優化後的渲染時間(秒)
Firefox 0.75 0.70
Chrome 1.85 1.08
Edge 5.53 2.47

 

 

 

 

 

注:

1. 每次頁面重新整理結果都有一定的差異,這個取的是多次執行的中間值。

2. 優化後的結果需要等FineUIPro v5.6.0 釋出後自行到官網示例測試,目前沒有線上測試連結。

 

可以看到,經過程式碼優化後,Chrome的效能有明顯的提升,但即使如此,Firefox還是比Chrome有效能優勢,只不過不再那麼辣眼睛了。

 

發現新問題

看似一個問題的結束,卻是另一個問題的開始,還記得上一篇文章中我們提到 Chrome 下選中卡頓的問題嗎?

即使在上述資料優化之後,Chrome的渲染效能有明顯提升的情況下(從1.85s提升到1.08s之後),Chrome下的行選中依然有明顯的卡頓現象,對比下幾個瀏覽器下的動圖:

Chrome:

 

Firefox:

 

Edge:

 

Chrome你這是要鬧哪樣?即使頁面渲染慢得多的Edge都沒有卡頓,選中行時非常絲滑,而Chrome就像被卡著脖子一樣,每次點選都有差不多0.5秒的延遲!

真不省心,真不省心.....

 

解決問題

這個問題的解決可以說是費盡周折,因為已經明確知道是Chrome瀏覽器的BUG,而Firefox和Edge都正常,所以根本不能按照常規思路去解釋。

後來,一個偶爾的機會,發現去掉第一列(包含複選框的那一列),問題神奇般的消失了,所以我一度懷疑是複選框的樣式問題,來看一下。
複選框的HTML結構很簡單:

<i class="f-icon f-iconfont f-grid-checkbox f-checkbox"></i>

CSS程式碼:

.f-checkbox {
    position: relative;
    top: 0;
    left: 0;
    display: inline-block;
    width: 14px;
    height: 14px;
    min-width: 14px;
    margin: 3px 1px;
    border-width: 1px;
    border-style: solid;
    border-radius: 2px;
}
.f-checkbox:after {
    display: table;
    position: absolute;
    left: 4px;
    top: 1px;
    width: 5px;
    height: 8px;
    border-width: 2px;
    border-style: solid;
    border-color: #fff;
    border-top: 0;
    border-left: 0;
    content: " ";
    -webkit-transform: rotate(45deg) scale(0);
    transform: rotate(45deg) scale(0);
    opacity: 0;
    filter: alpha(opacity=0);
}
.f-checkbox.f-checked {
    background-color: #007465;
    border-color: #007465;
}
.f-checkbox.f-checked:after {
    width: 5px;
    height: 8px;
    left: 4px;
    top: 1px;
    -webkit-transform: rotate(45deg) scale(1);
    transform: rotate(45deg) scale(1);
    opacity: 1;
    filter: alpha(opacity=100);
}

這段CSS程式碼我看了很久很久,實在找不到可以優化的地方,因為這個做法也是業內所公認的,通過將 f-checkbox:after 的 L 型邊框旋轉 45 度來實現對勾的效果。

 

接下來,神奇的事情發生了,一個偶然的機會,我會外層的 .f-grid-cell-inner 的 position: relative 去掉,所有的卡頓不見了,一切都像Firefox一樣絲滑:

 

現在來看下去掉這個 CSS 屬性之後,行選中的效果,絲滑的就像Firefox一樣:

 

問題解決了,是不是很高興?

可惜一點都高興不起來,首先不知道這個 td -> div 的 position:relative 挨著誰的事了,這麼不受 Chrome 的待見。

其次這個屬性雖然FineUIPro沒有大用處,還是有一點用處的,比如這裡:

所以遇到這種情況,就先加個例外好了。

 

不管怎麼說,也算是暫時畫上一個句號,看Chrome哪個版本能修正類似的問題?

 

 

不忘初心,砥礪前行!