場景
場景是大屏頁面一張深色背景, 里面一些文本元素以及圖表展示.
結果在IE下發現加載異常緩慢, 還有部分人員反饋頁面卡死.
后台讀寫優化
默認處理圖片邏輯是, ImageIO讀取原圖, 轉成byte[], base64編碼后, 放到dom里.
這樣圖片越大, 后台轉的byte[]數組越大也越卡, 那么改進思路自然是壓縮, 以及去除ImageIO讀取.
使用Thumbnailator, 對超過1MB的圖片進行壓縮, 一般10MB的深色圖片,
壓縮率用75%, 壓縮后也就幾百KB. 然后把base64編碼寫在dom里的實現方式改成了css加載src.
改完之后, 后台已經完全不涉及到讀寫圖片卡頓問題了.
圖片加載方式
但是前台依然會空白很久, 然后出現加載圖標, 最后才開始各個組件加載渲染. 那么這個空白跟圖片背景有沒有關系呢?
答案是no, 不過圖片會占用服務器帶寬, 所以需要壓縮下原圖或者直接放到cdn上.
關於圖片渲染是否影響內容加載可以做個很簡單的實驗, 將Chrome控制台調整到Network,
選擇fast3g網絡模式, 可以模擬一個低速網絡.
訪問一張帶背景圖的表單, 可以看到內容是先渲染出來的, 然后是加載圖片.
圖片是一段一段的加載的, 並不會影響內容主體渲染, 也不是導致初始頁面空白的元凶.
如果覺得圖片分段加載效果不好的話, 可以把圖片改成漸進式加載. 效果如下:
可以明顯看到圖片從模糊到清晰的一個過程, 企業微信里聊天傳輸圖片用的也是漸進式加載.
如何生成漸進式圖片呢? 只需要在photoshop編輯圖片的時候, 選擇交錯保存PNG.
也可以用代碼處理, 設置ProgressiveMode即可.
1 File file = new File("D:/o.jpg"); 2 BufferedImage image = ImageIO.read(file); 3 Iterator<ImageWriter> it = ImageIO.getImageWritersByFormatName("jpeg"); 4 ImageWriter writer = null; 5 while (it.hasNext()) { 6 writer = it.next(); 7 break; 8 } 9 if (writer != null) { 10 ImageWriteParam params = writer.getDefaultWriteParam(); 11 params.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // 設置可否壓縮 12 params.setCompressionQuality(0.75f); // 設置壓縮質量參數 13 params.setProgressiveMode(ImageWriteParam.MODE_DEFAULT); 14 ImageOutputStream output = ImageIO.createImageOutputStream(new File("D:/progressive.jpg")); 15 writer.setOutput(output); 16 writer.write(null, new IIOImage(image, null, null), params); 17 output.flush(); 18 writer.dispose(); 19 } 20 }
重復一下, 圖片漸進式和分段式, 只是提升交互體驗, 加載速度並沒有變化.
IE與Gzip
如果不是圖片導致的加載慢, 為什么很多小伙伴反饋大屏慢呢? IE以及Edge似乎更卡一點.
我們用Chrome訪問一張大屏模板, 對比下IE訪問模板的響應時間. 兩者都預先清理緩存.
訪問大屏地址 http://106.15.45.188:8088/WebReport/ReportServer?op=fs_main&cmd=entry_report&id=2571
截圖一看清楚了, IE里看上去Gzip就沒起作用, 實實在在的加載原js. 用了4s才加載完.
看下代碼中Gzip的處理, 直接把 IE全家 列到不支持Gzip的列表里了.
1 public boolean supportGzip() { 2 return !(isIE()) && !(isWebkit() && J2EEContainer.isWebLogic()); 3 } 4 5 public boolean isIE() { 6 //ie10之后不能根據msie判斷需根據trident,先帶上edge看看 7 return "msie".equals(this.browser) || this.userAgent.contains("trident") || this.userAgent.contains("edge"); 8 }
實際上高版本IE早就支持Gzip了, 因為IE11里http的響應頭已經寫了Accept-Encoding: gzip, deflate.
找了早期的IE9看了下, 也是支持Gzip壓縮的.
修復驗證
因為是線上環境, 我們本地沒還原客戶那邊的卡頓很久空白的情況, 猜測跟網速有關系.
需要用一個軟件來模擬低速網絡環境,. 首選自然是fiddler, 只需要一步設置即可.
Rules → Performances → Simulate Modem Speeds.
重復上述訪問entry操作, 等得的快炸的時候, 頁面終於加載出來了.
低速網絡下, 兩個js累計加載耗時561s!!!
開啟Gzip后, 跟Chrome速度一樣了, 兩個js累計114s, 越是低速網絡, Gzip效果越明顯.