近幾年,隨著移動互聯(lián)網(wǎng)強(qiáng)勢崛起,越來越多的網(wǎng)民開始在手機(jī)上“沖浪”。各大移動廠商為了吸引用戶的瀏覽,開始制作布局越來越復(fù)雜,效果越來越炫的移動應(yīng)用產(chǎn)品。然而隨之而來,也帶來了越來越多的問題,比如:文件越來越大、下載和運(yùn)行速度越來越慢等等。這些問題的影響,直接導(dǎo)致用戶的流失率越來越高。據(jù)統(tǒng)計(jì):

從圖中可以得知71%的用戶期望移動頁面跟pc頁面一樣快,74%的用戶能容忍的響應(yīng)時間為5秒,所以我們必須保證移動端頁面有足夠的速度。
移動頁面的速度跟三個因素有關(guān),分別是:移動網(wǎng)絡(luò)帶寬速度,設(shè)備性能(CPU,GPU,瀏覽器),頁面本身。
作為一個開發(fā)者,用戶所處的移動網(wǎng)絡(luò)帶寬環(huán)境,以及所擁有的設(shè)備是我們不能控制的。但是頁面本身的大小,是我們可以通過自己的手段,去完善和提升的。
接下來我們來聊聊具體如何去優(yōu)化移動端頁面。
首先我們得關(guān)注一下一個頁面從開始到呈現(xiàn)完畢需要經(jīng)歷什么階段,主要有四個階段:

(一)從圖中可以明顯得知,在頁面加載這一環(huán)節(jié),占據(jù)了大部分的時間。因而從加載這一環(huán)節(jié)去考慮如何去優(yōu)化頁面。
常規(guī)的手段有這幾種 1. 預(yù)加載 2.按需加載
(1) 預(yù)加載

這種加載方式可以提升用戶的體驗(yàn)感,讓用戶在等待頁面加載的過程中,不會覺得那么枯燥。
(2)按需加載

這種加載方式是盡量讓首屏的資源記載完成,首屏以外的資源在首屏加載結(jié)束后進(jìn)行記載,這樣也能就節(jié)省加載的時間,提升用戶體驗(yàn)。
(二)接下來從圖片資源進(jìn)行考慮。
一個移動端的頁面,圖片的大小還是占據(jù)一定比例的。因而我們需要對圖片資源進(jìn)行壓縮。常用的圖片壓縮網(wǎng)站可以使用 https://tinypng.com/
然而針對不同的圖片文件格式,jpg:建議使用大尺寸大有損壓縮比的jpg,png:建議多彩圖片使用png24、低彩圖片使用png8。
(三)從點(diǎn)擊事件的角度考慮
在移動端使用click點(diǎn)擊事件,會存大約 300 毫秒的等待時間。為什么這么設(shè)計(jì)呢? 因?yàn)樗肟纯茨闶遣皇且M(jìn)行雙擊(double tap)操作。為了讓這300毫秒的等待時間消失,我們可以引入fastclick.js這個庫。
(四)接下來我們從渲染的角度進(jìn)行思考"重繪和重排"
瀏覽器下載完頁面中的所有組件——HTML標(biāo)記、JavaScript、CSS、圖片之后會解析生成兩個內(nèi)部數(shù)據(jù)結(jié)構(gòu)——DOM樹和渲染樹。
DOM樹表示頁面結(jié)構(gòu),渲染樹表示DOM節(jié)點(diǎn)如何顯示。DOM樹中的每一個需要顯示的節(jié)點(diǎn)在渲染樹種至少存在一個對應(yīng)的節(jié)點(diǎn)(隱藏的DOM元素disply值為none 在渲染樹中沒有對應(yīng)的節(jié)點(diǎn))。渲染樹中的節(jié)點(diǎn)被稱為“幀”或“盒",符合CSS模型的定義,理解頁面元素為一個具有填充,邊距,邊框和位置的盒子。一旦DOM和渲染樹構(gòu)建完成,瀏覽器就開始顯示(繪制)頁面元素。
當(dāng)DOM的變化影響了元素的幾何屬性(寬或高),瀏覽器需要重新計(jì)算元素的幾何屬性,同樣其他元素的幾何屬性和位置也會因此受到影響。瀏覽器會使渲染樹中受到影響的部分失效,并重新構(gòu)造渲染樹。這個過程稱為重排。完成重排后,瀏覽器會重新繪制受影響的部分到屏幕,該過程稱為重繪。由于瀏覽器的流布局,對渲染樹的計(jì)算通常只需要遍歷一次就可以完成。但table及其內(nèi)部元素除外,它可能需要多次計(jì)算才能確定好其在渲染樹中節(jié)點(diǎn)的屬性,通常要花3倍于同等元素的時間。這也是為什么我們要避免使用table做布局的一個原因。
并不是所有的DOM變化都會影響幾何屬性,比如改變一個元素的背景色并不會影響元素的寬和高,這種情況下只會發(fā)生重繪。
提高網(wǎng)頁性能,就是要降低"重排"和"重繪"的頻率和成本,盡量少觸發(fā)重新渲染。
DOM變動和樣式變動,都會觸發(fā)重新渲染。但是,瀏覽器已經(jīng)很智能了,會盡量把所有的變動集中在一起,排成一個隊(duì)列,然后一次性執(zhí)行,盡量避免多次重新渲染。
div.style.color = 'blue';
div.style.marginTop = '30px';
上面代碼中,div元素有兩個樣式變動,但是瀏覽器只會觸發(fā)一次重排和重繪。
如果寫得不好,就會觸發(fā)兩次重排和重繪。
div.style.color = 'blue';
var margin = parseInt(div.style.marginTop);
div.style.marginTop = (margin + 10) + 'px';
上面代碼對div元素設(shè)置背景色以后,第二行要求瀏覽器給出該元素的位置,所以瀏覽器不得不立即重排。
重排和重繪是DOM編程中耗能的主要原因之一,平時涉及DOM編程時可以參考以下幾點(diǎn):
1.盡量不要在布局信息改變時做查詢(會導(dǎo)致渲染隊(duì)列強(qiáng)制刷新)
2.同一個DOM的多個屬性改變可以寫在一起(減少DOM訪問,同時把強(qiáng)制渲染隊(duì)列刷新的風(fēng)險降為0)
3.將需要多次重排的元素,position屬性設(shè)為absolute或fixed,這樣此元素就脫離了文檔流,它的變化不會影響到其他元素。例如有動畫效果的元素就最好設(shè)置為絕對定位。
渲染的另一個角度,移動端的動畫我們盡量使用css3進(jìn)行處理,少用js。這樣可以減少腳本的加載,可利用硬件進(jìn)行加速,可規(guī)避渲染樹的計(jì)算渲染更快。
最后總結(jié)如下:

其實(shí)從任何角度的優(yōu)化都是具有兩面性的,比如圖片壓縮,在減少資源體積的同時,可能會帶來圖片失真的影響。按需加載提升了速度,但可能導(dǎo)致大量的重繪等等各方面的影響。類似的矛盾在優(yōu)化過程也許碰到很多。需要根據(jù)自己業(yè)務(wù)的實(shí)際情況進(jìn)行權(quán)衡考量。
謝謝以下文章進(jìn)行的贊助:
http://www.cnblogs.com/zichi/p/4720000.html
http://www.itdecent.cn/p/f69b476a7200