淺談前端性能優(yōu)化(移動(dòng)端)

上一篇講了PC端的部分:前端性能優(yōu)化(PC端),這次繼續(xù)說(shuō)移動(dòng)端的。相對(duì)于PC端的,移動(dòng)web瀏覽器上有一些明顯的特點(diǎn):設(shè)備的屏幕小、新特性兼容性較好、支持一些比較新的HTML5和CSS3、需要與Native應(yīng)用交互等。但移動(dòng)端可用的CPU資源和網(wǎng)絡(luò)資源極為有限,因此要做好移動(dòng)端web上的優(yōu)化往往需要考慮做更多的事情。首先在移動(dòng)web的前端頁(yè)面渲染中,PC的優(yōu)化規(guī)則同樣適用,此外針對(duì)瀏覽器也要做一些更細(xì)節(jié)的優(yōu)化達(dá)到更好的效果。需要注意的是,并不是移動(dòng)端的優(yōu)化在PC端不適用,而是由于兼容性的原因,一些優(yōu)化規(guī)則在移動(dòng)端更具有代表性,所以也是為什么我把DNS預(yù)解析,離線緩存,HTTP2協(xié)議,GPU加速等東西放到這部分來(lái)講...

和上部分一樣,只是提供索引,涉及的知識(shí)點(diǎn)比較多請(qǐng)自行搜索

網(wǎng)絡(luò)加載類

1. 首屏數(shù)據(jù)請(qǐng)求提前,避免JavaScript文件加載后才請(qǐng)求渲染

為了進(jìn)一步提示頁(yè)面加載速度,可以考慮將頁(yè)面的數(shù)據(jù)請(qǐng)求盡可能提前,避免在JavaScript文件加載完成后才去請(qǐng)求數(shù)據(jù)。通常數(shù)據(jù)請(qǐng)求是頁(yè)面內(nèi)容渲染中關(guān)鍵路徑最長(zhǎng)的部分,而且不能并行,所以如果數(shù)據(jù)請(qǐng)求能提前的話,可以極大程度上縮短頁(yè)面內(nèi)容的渲染完成時(shí)間。

2. 首屏加載和按需加載,非首屏內(nèi)容滾屏加載,保證首屏內(nèi)容最小化

由于移動(dòng)端網(wǎng)絡(luò)相對(duì)較慢,網(wǎng)絡(luò)資源有限,因此為了保證盡快完成頁(yè)面內(nèi)容的加載,需要保證首屏加載資源的最小化,非首屏的內(nèi)容使用滾動(dòng)的方式異步加載。一般推薦移動(dòng)端頁(yè)面首屏數(shù)據(jù)展示延遲不超過(guò)3秒。

3. 模塊化資源并行下載

主要指模塊化JavaScript資源的異步加載,例如AMD的異步模塊,使用并行的加載方式能夠縮短多個(gè)文件資源的加載時(shí)間。

4. inline首屏必備的CSS和JavaScript

通常為了在HTML加載完成時(shí)能使瀏覽器中有基本的樣式,需要將頁(yè)面渲染時(shí)必備的CSS和JS通過(guò)script或style的方式內(nèi)聯(lián)到頁(yè)面中,避免頁(yè)面HTML載入完成到頁(yè)面內(nèi)容展示這段過(guò)程中頁(yè)面出現(xiàn)空白

5. meta dns prefetch設(shè)置DNS預(yù)解析

設(shè)置文件資源的DNS預(yù)解析,能讓瀏覽器提前解析獲取靜態(tài)資源的主機(jī)IP,避免等到請(qǐng)求的時(shí)候才發(fā)起DNS解析。

<!-- cdn域名預(yù)解析 -->
<meta http-equiv='x-dns-prefetch-control' content='on'>
<link rel="dns-prefetch" >

6. 資源預(yù)加載

首屏加載完成后可能會(huì)使用的資源,我們可以用 link標(biāo)簽聲明特定文件的預(yù)加載

<link rel='subresource' href='main.css'>

<link rel='prefetch' href='secondary.js'>

注意:只有可緩存的資源才進(jìn)行預(yù)加載,否則浪費(fèi)資源!

7. Pre render預(yù)渲染

預(yù)渲染意味著我們提前加載好用戶即將訪問(wèn)的下一個(gè)頁(yè)面,否則進(jìn)行預(yù)渲染這個(gè)頁(yè)面將浪費(fèi)資源,慎用!

<link rel='prerender' href='//j.autohome.com.cn'>

8. 合理利用MTU策略

通常情況下,TCP網(wǎng)絡(luò)傳輸?shù)淖畲髠鬏攩卧∕TU)為1500B,即一個(gè)RTT(Round-Trip Time,網(wǎng)絡(luò)請(qǐng)求返回時(shí)間)內(nèi)可以傳輸?shù)臄?shù)據(jù)量最大為1500字節(jié)(為什么以太網(wǎng)mtu值被設(shè)定為1500 - 知乎)。因此在前后端分離的開發(fā)模式中,盡量保證頁(yè)面的HTML內(nèi)容在1KB以內(nèi),這樣整個(gè)HTML內(nèi)容的請(qǐng)求就可以在一個(gè)RTT內(nèi)完成,最大限度的提高了HTML載入速度

緩存

1. 合理利用瀏覽器緩存

除了上一節(jié)說(shuō)到的Cache-Control、Expires、Etag和Last-Modified來(lái)設(shè)置HTTP緩存外,在移動(dòng)端還可以使用localstorage等來(lái)保存ajax返回的數(shù)據(jù),或者使用localstorage保存CSS或JS等靜態(tài)資源,實(shí)現(xiàn)移動(dòng)端的離線應(yīng)用,盡可能的減少網(wǎng)絡(luò)請(qǐng)求,保證靜態(tài)資源內(nèi)容的快速加載。

2. 靜態(tài)資源離線方案

對(duì)于移動(dòng)端或者混合應(yīng)用,可以設(shè)置離線文件或離線包機(jī)制讓靜態(tài)資源請(qǐng)求從本地讀取,加快資源載入速度,并實(shí)現(xiàn)離線更新。這塊推薦葉小釵大神的前端優(yōu)化帶來(lái)的思考,淺談前端工程化 可以挑著看。離線資源這塊東西太多了,以后有時(shí)間單獨(dú)拿出來(lái)寫

3. 嘗試使用 AMP HTML

AMP HTML 可以作為優(yōu)化前端頁(yè)面性能的一個(gè)解決方案,使用AMP Component中的元素來(lái)代替原始頁(yè)面元素進(jìn)行直接渲染 [譯]關(guān)于谷歌的AMP,你需要知道這些。

圖片類

1. 圖片壓縮處理

移動(dòng)端通常要保證頁(yè)面中一切用到的圖片都是經(jīng)過(guò)壓縮優(yōu)化處理,而不是以原圖的形式直接使用的,因?yàn)槟菢雍芟牧髁浚⑶壹虞d時(shí)間更長(zhǎng)。

2. 使用較小的圖片,合理使用base64內(nèi)嵌圖片

在頁(yè)面使用的背景圖片不多且比較小的情況下,可以把圖片轉(zhuǎn)成base64編碼嵌入到html頁(yè)面或者CSS文件中,這樣可以減少頁(yè)面的HTTP請(qǐng)求數(shù)。需要注意的是,要保證圖片較小,一般超過(guò)5kb的就不推薦base64嵌入顯示了(前端開發(fā)中,使用base64圖片的弊端是什么? - 知乎

3. 使用更高壓縮比格式的圖片

使用具有較高壓縮比格式的圖片,如webp等。在同等圖片畫質(zhì)的情況下,高壓縮比格式的圖片體積更小,能夠更快的完成文件傳輸,節(jié)省網(wǎng)站流量。

![](//x.autoimg.cn/path/photo.webp)

4. 圖片懶加載

為了保證頁(yè)面內(nèi)容最小化,加速頁(yè)面渲染,盡可能節(jié)省首屏網(wǎng)絡(luò)流量,頁(yè)面中的圖片資源推薦使用懶加載實(shí)現(xiàn),在頁(yè)面滾動(dòng)時(shí)動(dòng)態(tài)載入圖片。

5. 使用Media Query 或者 srcset 根據(jù)不同屏幕加載不同大小的圖片

針對(duì)不同屏幕尺寸和分辨率,輸出不同大小的圖片或者背景圖能保證用戶體驗(yàn)不降低的前提下節(jié)省網(wǎng)絡(luò)流量,加快部分機(jī)型圖片載入速度,這在移動(dòng)端非常值得推薦

6. 使用iconfont代替圖片圖標(biāo)

iconfont體積較小而且是矢量圖,因此縮放不會(huì)失真,還可以方便修改圖片大小和呈現(xiàn)的顏色,但是需要注意iconfont引用不同webfont格式會(huì)有兼容問(wèn)題。

7. 定義圖片大小限制

加載單張圖片不建議超過(guò)30KB,避免大圖片加載時(shí)間過(guò)長(zhǎng)而阻塞頁(yè)面其他資源的下載。如果用戶上傳的圖片過(guò)大,建議設(shè)置限制。

腳本類

1. 盡量使用id選擇器

選擇頁(yè)面DOM元素時(shí)盡量使用id選擇器,因?yàn)閕d選擇器速度最快

2. 合理的緩存dom對(duì)象

對(duì)于需要重復(fù)使用的dom對(duì)象,要優(yōu)先設(shè)置緩存變量,避免每次使用時(shí)都要從整個(gè)dom樹重新查找。

// 不推薦
$("#mod .active").removeClass('active');
$("#mod .not-active").addClass("active");

// 推薦
const $mod = $("#mod");
$mod.find(".active").removeClass("active")
$mod.find(".not-active").addClass("active")

jq 上有很多優(yōu)化建議,詳情搜索JQ 優(yōu)化

3. 頁(yè)面元素盡量使用事件代理,避免事件直接綁定

使用事件代理可以避免對(duì)每個(gè)元素都進(jìn)行綁定。并且可以避免出現(xiàn)內(nèi)存泄漏以及需要?jiǎng)討B(tài)添加元素的事件綁定問(wèn)題

// 不推薦
$(".btn").click( _ => console.log("hello") )

// 推薦
$(document).on("click", ".btn", _ => console.log("world"))

4. 使用touch代理click

由于移動(dòng)端屏幕的設(shè)計(jì),touch事件和click事件觸發(fā)之間存在300ms延遲,所以在頁(yè)面沒有touchmove實(shí)現(xiàn)滾動(dòng)處理的情況,可以用touchstart代替元素的click事件,加快頁(yè)面點(diǎn)擊的響應(yīng)速度,提高用戶體驗(yàn)。但同時(shí)也需要注意頁(yè)面重疊元素touch動(dòng)作的點(diǎn)透問(wèn)題。

// 不推薦
$("body").on("click",".btn",function(){ console.log(this) });

// 推薦
$("body").on("tap",".btn",function(){ console.log(this) });
// tap為zepto用touch事件封裝的

5. 避免touchmove,scroll等連續(xù)事件處理

需要對(duì)這類高頻觸發(fā)回調(diào)的事件設(shè)置函數(shù)節(jié)流(throttle | debounce),避免頻繁的事件調(diào)用導(dǎo)致移動(dòng)端頁(yè)面卡頓

6. 避免使用eval、with,使用join代替連接符+,推薦使用ES6的模板字符串

基本的安全腳本編寫問(wèn)題,盡可能使用高效率的特性來(lái)完成這些操作,避免不規(guī)范或者不安全的寫法。

7. 盡量使用ES6+的特性來(lái)編程

ES6+在一定程度上更高效,在chrome59版本對(duì)ES6做了深度優(yōu)化之后,很多特性速度提升了80%左右,這也是未來(lái)規(guī)范的需要。ES8前段時(shí)間也已經(jīng)落地了,如果你還沒有掌握ES6語(yǔ)法的話,抓緊時(shí)間學(xué)吧...

渲染類

1. 使用viewport固定屏幕渲染,可以加速頁(yè)面渲染內(nèi)容

一般認(rèn)為,在移動(dòng)端設(shè)置viewport可以加速頁(yè)面的渲染,同時(shí)可以避免縮放導(dǎo)致頁(yè)面重排重繪。

// 利用meta標(biāo)簽對(duì)viewport進(jìn)行控制
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

2. 避免各種形式重排(reflow)重繪(redraw)

頁(yè)面的重排重繪很耗性能,所以一定要盡可能減少頁(yè)面的重排重繪,例如頁(yè)面圖片大小變化、元素位置變化這些情況都會(huì)導(dǎo)致重排與重繪

3. 使用CSS3動(dòng)畫,開啟GPU加速

使用CSS3動(dòng)畫可以設(shè)置transform: translateZ(0)來(lái)開啟移動(dòng)設(shè)備瀏覽器的GPU圖形處理加速。這里安利一波京東凹凸實(shí)驗(yàn)室,講的挺好的,GPU加速是什么

4. 合理使用canvas和requestAnimationFrame

選擇canvas或者requestAnimationFrame等更高效的動(dòng)畫實(shí)現(xiàn)方式,避免使用settimeout、setInterval等方式直接處理連續(xù)動(dòng)畫

5. SVG代替圖片

部分情況下可以考慮使用SVG代替圖片實(shí)現(xiàn)動(dòng)畫,因?yàn)镾VG格式內(nèi)容更小,而且SVG的DOM結(jié)構(gòu)方便調(diào)整

6. 不濫用float

在DOM渲染樹生成后的布局渲染階段,使用float的元素布局計(jì)算比較耗性能,所以盡量減少float的使用,推薦使用固定布局或者flex布局的方式來(lái)實(shí)現(xiàn)頁(yè)面的元素布局

7. 不濫用web字體或過(guò)多的font-size聲明

過(guò)多的font-size聲明會(huì)增加字體的計(jì)算大小,而且也沒啥必要

架構(gòu)協(xié)議

1. 嘗試使用SPDY和HTTP2

在條件允許的情況下可以考慮使用SPDY協(xié)議來(lái)進(jìn)行文件資源傳輸,利用連接復(fù)用加快傳輸過(guò)程,縮短資源加載時(shí)間。HTTP2在未來(lái)也一定會(huì)成為主流的

2. 使用后端數(shù)據(jù)渲染

SSR( Server Side Rendering,服務(wù)端渲染)的方式可以加速頁(yè)面內(nèi)容的渲染展示,避免空白頁(yè)面的出現(xiàn),同時(shí)可以解決頁(yè)面SEO的問(wèn)題。條件允許的話,SSR是一個(gè)很好的實(shí)踐思路。百度SSP單頁(yè)式應(yīng)用性能優(yōu)化實(shí)踐React 同構(gòu)實(shí)踐與思考

3. 使用Native View代替DOM的性能劣勢(shì)

可以嘗試使用Native View的MNV* 開發(fā)模式來(lái)避免HTML DOM性能慢的問(wèn)題,目前使用MNV* 的開發(fā)模式已經(jīng)可以將頁(yè)面內(nèi)容渲染體驗(yàn)做到接近客戶端Native應(yīng)用的體驗(yàn)了。


關(guān)于頁(yè)面優(yōu)化的常用技術(shù)手段和思路主要包括以上這些,有部分遺漏歡迎補(bǔ)充。大家可以根據(jù)需要將這些方法應(yīng)用到自己的項(xiàng)目中去,想全部做到幾乎是不可能的,但做到用戶可以接受的程度還是很容易的。

軟件工程沒有銀彈,在我們做到了極致優(yōu)化的同時(shí)也需要付出很大的代價(jià),這也是前端優(yōu)化的一個(gè)問(wèn)題。理論上這些優(yōu)化都可以實(shí)現(xiàn),但是我們也要懂得權(quán)衡,優(yōu)化提升了用戶體驗(yàn),使數(shù)據(jù)加載更快,但是項(xiàng)目代碼卻可能打亂,異步內(nèi)容要拆分出來(lái),首屏雪碧圖可能要拆分2個(gè)或更多,項(xiàng)目代碼維護(hù)成本成倍增加,項(xiàng)目結(jié)構(gòu)也可能變得混亂。任何一部分優(yōu)化都可以做得很深入,但不一定都值得。在優(yōu)化的同時(shí)考慮性價(jià)比,這才是我們作為一名前端工程師處理前端優(yōu)化時(shí)該具有的正確思維。

PS:另外身位一個(gè)coder,雖然晚睡是常態(tài)了,但每次寫東西都是熬到半夜2、3點(diǎn)身體也吃不消啊!! 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 網(wǎng)絡(luò)加載類 首屏數(shù)據(jù)請(qǐng)求提前,避免JavaScript文件加載后才請(qǐng)求渲染為了進(jìn)一步提示頁(yè)面加載速度,可以考慮將頁(yè)...
    fangdown閱讀 774評(píng)論 0 1
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,030評(píng)論 25 709
  • 圍繞前端的性能多如牛毛,涉及到方方面面,以我我們將圍繞PC瀏覽器和移動(dòng)端瀏覽器的優(yōu)化策略進(jìn)行羅列注意,是羅列不是展...
    流動(dòng)碼文閱讀 743評(píng)論 0 0
  • 前言 前端的工作并不僅僅是實(shí)現(xiàn)「視覺&交互稿」,想要開發(fā)一個(gè)高性能易維護(hù)的「完美」站點(diǎn)并未易事,針對(duì)前端的性能優(yōu)化...
    木羽zwwill閱讀 716評(píng)論 0 4
  • 2015年春,從包頭去成陵的路上路過(guò)響沙灣,小徐說(shuō):“在響沙灣,從沙丘上往下滑,沙子會(huì)發(fā)出轟隆隆的聲音”。 ...
    丫頭利貞閱讀 794評(píng)論 0 1

友情鏈接更多精彩內(nèi)容