前端效能優化 —— 移動端瀏覽器優化策略
摘要: 前端效能優化是一個很寬泛的概念,本書前面的部分也多多少少提到一些前端優化方法,這也是我們一直在關注的一件重要事情。配合各種方式、手段、輔助系統,前端優化的最終目的都是提升使用者體驗,改善頁面效能,我們常常竭盡全力進行前端頁面優化,但卻忽略了這樣做的效果和意義。先不急於探究前端優化具體可以怎樣去做,先看看什麼是前端效能,應該怎樣去了解和評價前端頁面的效能。
相對於桌面端瀏覽器,移動端Web瀏覽器上有一些較為明顯的特點:裝置螢幕較小、新特性相容性較好、支援一些較新的HTML5和CSS3特性、需要與Native應用互動等。但移動端瀏覽器可用的CPU計算資源和網路資源極為有限,因此要做好移動端Web上的優化往往需要做更多的事情。
首先,在移動端Web的前端頁面渲染中,桌面瀏覽器端上的優化規則同樣適用,此外針對移動端也要做一些極致的優化來達到更好的效果。需要注意的是,並不是移動端的優化原則在桌面瀏覽器端就不適用,而是由於相容性和差異性的原因,一些優化原則在移動端更具代表性。
一、網路載入類
1.首屏資料請求提前,避免JavaScript檔案載入後才請求資料
為了進一步提升頁面載入速度,可以考慮將頁面的資料請求儘可能提前,避免在JavaScript載入完成後才去請求資料。通常資料請求是頁面內容渲染中關鍵路徑最長的部分,而且不能並行,所以如果能將資料請求提前,可以極大程度上縮短頁面內容的渲染完成時間。
2.首屏載入和按需載入,非首屏內容滾屏載入,保證首屏內容最小化
由於移動端網路速度相對較慢,網路資源有限,因此為了儘快完成頁面內容的載入,需要保證首屏載入資源最小化,非首屏內容使用滾動的方式非同步載入。一般推薦移動端頁面首屏資料展示延時最長不超過3秒。目前中國聯通3G的網路速度為338KB/s(2.71Mb/s),所以推薦首屏所有資源大小不超過1014KB,即大約不超過1MB。
3.模組化資源並行下載
在移動端資源載入中,儘量保證JavaScript資源並行載入,主要指的是模組化JavaScript資源的非同步載入,例如AMD的非同步模組,使用並行的載入方式能夠縮短多個檔案資源的載入時間。
4.inline首屏必備的CSS和JavaScript
通常為了在HTML載入完成時能使瀏覽器中有基本的樣式,需要將頁面渲染時必備的CSS和JavaScript通過或內聯到頁面中,避免頁面HTML載入完成到頁面內容展示這段過程中頁面出現空白。
樣例
/* 必備的首屏CSS */
html, body{
margin: 0;
padding: 0;
background-color: #ccc;
}
5.meta dns prefetch設定DNS預解析
設定檔案資源的DNS預解析,讓瀏覽器提前解析獲取靜態資源的主機IP,避免等到請求時才發起DNS解析請求。通常在移動端HTML中可以採用如下方式完成。
6.資源預載入
對於移動端首屏載入後可能會被使用的資源,需要在首屏完成載入後儘快進行載入,保證在使用者需要瀏覽時已經載入完成,這時候如果再去非同步請求就顯得很慢。
7.合理利用MTU策略
通常情況下,我們認為TCP網路傳輸的最大傳輸單元(Maximum Transmission Unit,MTU)為1500B,即網路一個RTT(Round-Trip Time,網路請求往返時間)時間內可以傳輸的資料量最大為1500位元組。因此,在前後端分離的開發模式中,儘量保證頁面的HTML內容在1KB以內,這樣整個HTML的內容請求就可以在一個RTT時間內請求完成,最大限度地提高HTML載入速度。
二、快取類
1.合理利用瀏覽器快取
除了上面說到的使用Cache-Control、Expires、Etag和Last-Modified來設定HTTP快取外,在移動端還可以使用localStorage等來儲存AJAX返回的資料,或者使用localStorage儲存CSS或JavaScript靜態資源內容,實現移動端的離線應用,儘可能減少網路請求,保證靜態資源內容的快速載入。
2.靜態資源離線方案
對於移動端或Hybrid應用,可以設定離線檔案或離線包機制讓靜態資源請求從本地讀取,加快資源載入速度,並實現離線更新。關於這塊內容,我們會在後面的章節中重點講解。
3.嘗試使用AMP HTML
AMP HTML可以作為優化前端頁面效能的一個解決方案,使用AMP Component中的元素來代替原始的頁面元素進行直接渲染。
Your browser doesn’t support HTML5 video
Your browser doesn’t support HTML5 video
三、圖片類
1.圖片壓縮處理
在移動端,通常要保證頁面中一切用到的圖片都是經過壓縮優化處理的,而不是以原圖的形式直接使用的,因為那樣很消耗流量,而且載入時間更長。
2.使用較小的圖片,合理使用base64內嵌圖片
在頁面使用的背景圖片不多且較小的情況下,可以將圖片轉化成base64編碼嵌入到HTML頁面或CSS檔案中,這樣可以減少頁面的HTTP請求數。需要注意的是,要保證圖片較小,一般圖片大小超過2KB就不推薦使用base64嵌入顯示了。
.class-name {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAALCAMAAABxsOwqAAAAYFBMVEWnxwusyQukxQudwQyZvgyhxAyfwgyxzAsUHQGOuA0aJAERGAFIXwSTugyEqgtqhghQZgUwQQIpOQKbuguVtQuKrAuCowp2kQlheghTbQZHWQU7SwVAVgQ6TgQlLwMeKwFOemyQAAAAVElEQVQI1y3JVRaAIAAF0UconXbvf5ei8HfPDIQQhBAAFE10iKig3SLRNN4SP/p+N08VC0YnfIlNWtqIkhg/TPYbCvhqdHAWRXPZSp3g3CWZvVLXC6OJA3ukv0AaAAAAAElFTkSuQmCC');
}
3.使用更高壓縮比格式的圖片
使用具有較高壓縮比格式的圖片,如webp等。在同等圖片畫質的情況下,高壓縮比格式的圖片體積更小,能夠更快完成檔案傳輸,節省網路流量。
4.圖片懶載入
為了保證頁面內容的最小化,加速頁面的渲染,儘可能節省移動端網路流量,頁面中的圖片資源推薦使用懶載入實現,在頁面滾動時動態載入圖片。
5.使用Media Query或srcset根據不同螢幕載入不同大小圖片
在介紹響應式的章節中我們瞭解到,針對不同的移動端螢幕尺寸和解析度,輸出不同大小的圖片或背景圖能保證在使用者體驗不降低的前提下節省網路流量,加快部分機型的圖片載入速度,這在移動端非常值得推薦。
6.使用iconfont代替圖片圖示
在頁面中儘可能使用iconfont來代替圖片圖示,這樣做的好處有以下幾個:使用iconfont體積較小,而且是向量圖,因此縮放時不會失真;可以方便地修改圖片大小尺寸和呈現顏色。但是需要注意的是,iconfont引用不同webfont格式時的相容性寫法,根據經驗推薦儘量按照以下順序書寫,否則不容易相容到所有的瀏覽器上。
@font-face {
font-family: iconfont;
src: url("./iconfont.eot");
src: url("./iconfont.eot?#iefix") format("eot"),
url("./iconfont.woff") format("woff"),
url("./iconfont.ttf") format("truetype");
}
7.定義圖片大小限制
載入的單張圖片一般建議不超過30KB,避免大圖片載入時間長而阻塞頁面其他資源的下載,因此推薦在10KB以內。如果使用者上傳的圖片過大,建議設定告警系統,幫助我們觀察瞭解整個網站的圖片流量情況,做出進一步的改善。
四、指令碼類
1.儘量使用id選擇器
選擇頁面DOM元素時儘量使用id選擇器,因為id選擇器速度最快。
2.合理快取DOM物件
對於需要重複使用的DOM物件,要優先設定快取變數,避免每次使用時都要從整個DOM樹中重新查詢。
// 不推薦
$('#mod .active').remove('active');
$('#mod .not-active').addClass('active');
// 推薦
let $mod = $('#mod');
$mod.find('.active').remove('active');
$mod.find('.not-active').addClass('active');
3.頁面元素儘量使用事件代理,避免直接事件繫結
使用事件代理可以避免對每個元素都進行繫結,並且可以避免出現記憶體洩露及需要動態新增元素的事件繫結問題,所以儘量不要直接使用事件繫結。
// 不推薦
$('.btn').on('click', function(e){
console.log(this);
});
// 推薦
$('body').on('click', '.btn', function(e){
console.log(this);
});
4.使用touchstart代替click
由於移動端螢幕的設計,touchstart事件和click事件觸發時間之間存在300毫秒的延時,所以在頁面中沒有實現touchmove滾動處理的情況下,可以使用touchstart事件來代替元素的click事件,加快頁面點選的響應速度,提高使用者體驗。但同時我們也要注意頁面重疊元素touch動作的點選穿透問題。
// 不推薦
$('body').on('click', '.btn', function(e){
console.log(this);
});
// 推薦
$('body').on('touchstart', '.btn', function(e){
console.log(this);
});
5.避免touchmove、scroll連續事件處理
需要對touchmove、scroll這類可能連續觸發回撥的事件設定事件節流,例如設定每隔16ms(60幀的幀間隔為16.7ms,因此可以合理地設定為16ms)才進行一次事件處理,避免頻繁的事件呼叫導致移動端頁面卡頓。
// 不推薦
$('.scroller').on('touchmove', '.btn', function(e){
console.log(this);
});
// 推薦
$('.scroller').on('touchmove', '.btn', function(e){
let self = this;
setTimeout(function(){
console.log(self);
}, 16);
});
6.避免使用eval、with,使用join代替連線符+,推薦使用ECMAScript 6的字串模板
這些都是一些基礎的安全指令碼編寫問題,儘可能使用較高效率的特性來完成這些操作,避免不規範或不安全的寫法。
7.儘量使用ECMAScript 6+的特性來程式設計
ECMAScript 6+一定程度上更加安全高效,而且部分特性執行速度更快,也是未來規範的需要,所以推薦使用ECMAScript 6+的新特性來完成後面的開發。
五、渲染類
1.使用Viewport固定螢幕渲染,可以加速頁面渲染內容
一般認為,在移動端設定Viewport可以加速頁面的渲染,同時可以避免縮放導致頁面重排重繪。在移動端固定Viewport設定的方法如下。
2.避免各種形式重排重繪
頁面的重排重繪很耗效能,所以一定要儘可能減少頁面的重排重繪,例如頁面圖片大小變化、元素位置變化等這些情況都會導致重排重繪。
3.使用CSS3動畫,開啟GPU加速
使用CSS3動畫時可以設定transform: translateZ(0)來開啟移動裝置瀏覽器的GPU圖形處理加速,讓動畫過程更加流暢。
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);
4.合理使用Canvas和requestAnimationFrame
選擇Canvas或requestAnimationFrame等更高效的動畫實現方式,儘量避免使用setTimeout、setInterval等方式來直接處理連續動畫。
5.SVG代替圖片
部分情況下可以考慮使用SVG代替圖片實現動畫,因為使用SVG格式內容更小,而且SVG DOM結構方便調整。
6.不濫用float
在DOM渲染樹生成後的佈局渲染階段,使用float的元素佈局計算比較耗效能,所以儘量減少float的使用,推薦使用固定佈局或flex-box彈性佈局的方式來實現頁面元素佈局。
7.不濫用web字型或過多font-size宣告
過多的font-size宣告會增加字型的大小計算,而且也沒有必要的。
六、架構協議類
1.嘗試使用SPDY和HTTP 2
在條件允許的情況下可以考慮使用SPDY協議來進行檔案資源傳輸,利用連線複用加快傳輸過程,縮短資源載入時間。HTTP 2在未來也是可以考慮嘗試的。
2.使用後端資料渲染
使用後端資料渲染的方式可以加快頁面內容的渲染展示,避免空白頁面的出現,同時可以解決移動端頁面SEO的問題。如果條件允許,後端資料渲染是一個很不錯的實踐思路。後面的章節會詳細介紹後端資料渲染的相關內容。
3.使用Native View代替DOM的效能劣勢
可以嘗試使用Native View的MNV開發模式來避免HTML DOM效能慢的問題,目前使用MNV的開發模式已經可以將頁面內容渲染體驗做到接近客戶端Native應用的體驗了。
關於頁面優化的常用技術手段和思路主要包括以上這些,儘管列舉出很多,但仍可能有少數遺漏,可見前端效能優化不是一件簡簡單單的事情,其涉及的內容很多。大家可以根據實際情況將這些方法應用到自己的專案當中,要想全部做到幾乎是不可能的,但做到使用者可接受的原則還是很容易實現的。
於此同時我們要清楚的是,在我們做到了極致優化的同時也付出了很大的代價,這也是前端優化的一個問題。理論上這些優化都是可以實現的,但是作為工程師我們也要明白懂得權衡。優化提升了使用者體驗,使資料載入更快,但是專案程式碼卻可能打亂,非同步內容要拆分出來,首屏的一個雪碧圖可能要分成兩個,頁面專案程式碼維護成本成倍增加,專案結構也可能變得混亂。
所以前期在設計構建、元件的解決方案時要解決好非同步的自動處理問題。任何一部分優化都可以做得很深入,但不一定都值得,在優化的同時也要儘量考慮價效比,這才是我們作為一名前端工程師處理前端優化時應該具有的正確思維。
相關文章
- 前端效能優化 之 瀏覽器快取前端優化瀏覽器快取
- 前端效能優化(一)——瀏覽器工作原理前端優化瀏覽器
- 桌面端前端效能優化策略前端優化
- 前端效能優化(二)——瀏覽器快取機制前端優化瀏覽器快取
- 移動端首屏優化策略優化
- 前端基於瀏覽器儲存的AJAX效能優化前端瀏覽器優化
- 從瀏覽器渲染原理談動畫效能優化瀏覽器動畫優化
- 使用React中後臺效能優化以及移動端優化React優化
- 使用vue中後臺效能優化以及移動端優化Vue優化
- 前端效能優化:細說瀏覽器渲染的重排與重繪前端優化瀏覽器
- 瀏覽器工作原理及web 效能優化(上)瀏覽器Web優化
- 瀏覽器層合成與頁面效能優化瀏覽器優化
- 【前端效能優化】vue效能優化前端優化Vue
- 移動端網頁效能優化自查表網頁優化
- 瀏覽器渲染流水線解析與網頁動畫效能優化瀏覽器網頁動畫優化
- 前端優化:瀏覽器快取技術介紹前端優化瀏覽器快取
- 前端效能優化之HTTP快取策略前端優化HTTP快取
- 前端效能優化(JS/CSS優化,SEO優化)前端優化JSCSS
- 前端效能優化 --- 圖片優化前端優化
- 移動應用效能優化優化
- 前端不止:Web效能優化–關鍵渲染路徑以及優化策略前端Web優化
- 前端效能優化前端優化
- 【高效能JS】重繪、重排與瀏覽器優化方法JS瀏覽器優化
- 前端css效能優化前端CSS優化
- web前端效能優化Web前端優化
- 前端效能優化指南前端優化
- 前端效能優化整理前端優化
- Android 效能優化 ---- 啟動優化Android優化
- 前端優化,瞭解瀏覽器重排與重繪前端優化瀏覽器
- 瀏覽器重繪(repaint)重排(reflow)與優化[瀏覽器機制]瀏覽器AI優化
- 前端效能優化JavaScript篇前端優化JavaScript
- 前端效能優化總結前端優化
- 前端效能優化基礎前端優化
- vue + webpack 前端效能優化VueWeb前端優化
- 前端效能優化之Lazyload前端優化
- 前端效能優化的點前端優化
- 前端效能優化小結前端優化
- 移動端圖片優化總結優化