寫(xiě)在前面
在公司做過(guò)項(xiàng)目都知道,一款產(chǎn)品性能的優(yōu)化非常重要,同時(shí)也是體現(xiàn)個(gè)人技術(shù)能力泵喘。
之前一直做算法,隨后在公司做平臺(tái)軟件及后臺(tái),一個(gè)產(chǎn)品開(kāi)發(fā)好-上線,優(yōu)化一直伴隨著整個(gè)過(guò)程,之前在公司做的一款平臺(tái)軟件,從上線到最終的穩(wěn)定幾乎花了一年時(shí)間,其中大部分都在做系統(tǒng)的優(yōu)化。
優(yōu)化的前提是軟件的業(yè)務(wù)架構(gòu)和數(shù)據(jù)設(shè)計(jì)的比較好,否則只能推到重來(lái).所以產(chǎn)品的架構(gòu)和數(shù)據(jù)庫(kù)的設(shè)計(jì)很重要惯疙。
言歸正轉(zhuǎn),今天要給大家講的是webApp的優(yōu)化,主要利用自己業(yè)余接的大大小小6-7款外包項(xiàng)目和幫朋友做的幾款項(xiàng)目以及自己平時(shí)測(cè)試過(guò)程中遇到的問(wèn)題給大家講講webApp相關(guān)的優(yōu)化方面的知識(shí),同時(shí)很多優(yōu)化都是參考了大量網(wǎng)上相關(guān)的技術(shù),在其基礎(chǔ)上進(jìn)行修改。
這里有說(shuō)的不好的請(qǐng)大家多多指教,或者有更好的解決辦法,望大家能夠指出,一起進(jìn)步!
看點(diǎn)
01
首先給大家列一個(gè)提綱:
1.前言
2.優(yōu)化動(dòng)力主要來(lái)源
3.開(kāi)發(fā)webAPP 有哪幾種方式
?3.1 單頁(yè)web應(yīng)用,如ExtJS,Backbone铐拐,AngularJS丢胚,Avalon等
? ? ?3.1.1單頁(yè)應(yīng)用現(xiàn)狀
? ? ?3.1.2其中部署上也存在這很大的差異
? ? ?3.1.3 單頁(yè)web局限性
? ? ?3.1.4對(duì)程序員掌握J(rèn)S語(yǔ)言程度 ? ?
?3.2 基于框架webAPP,如Ionic,React Native,MUI等
4 webAPP優(yōu)化方案
4.1 網(wǎng)絡(luò)傳輸優(yōu)化
? ?4.1.1 網(wǎng)絡(luò)傳輸?shù)膬?yōu)化要點(diǎn)
? ?4.1.2 首屏加速
? ?4.1.3 降低請(qǐng)求數(shù)量
? ?4.1.4 降低請(qǐng)求量
? ?4.1.5緩存Ajax/localstorage
? ?4.1.6 lazyload懶加載 ? ? ? ?
4.2 DOM操作優(yōu)化
? ?4.2.1 頁(yè)面渲染
? ?4.2.2 減少使用定位屬性(fixed/absolute)
4.3 內(nèi)存資源優(yōu)化
? ?4.3.1 虛擬鍵盤(pán)導(dǎo)致fixed元素錯(cuò)位
? ?4.3.2 fixed元素滑動(dòng)慣性平滑度
? ?4.3.3 其它
4.4 內(nèi)存資源優(yōu)化
? ?4.4.1 移動(dòng)端的javascript
? ?4.4.2 閉包陷阱
? ?4.4.3 webapp資源釋放
? ?4.4.4 動(dòng)畫(huà)與假死
? ?4.4.5 Application Cache
4.5 增強(qiáng)用戶體驗(yàn)優(yōu)化
? ? 4.5.1 區(qū)域滾動(dòng)
? ? 4.5.2 ?點(diǎn)擊響應(yīng)
首先來(lái)看看,我們給一款產(chǎn)品做優(yōu)化的來(lái)源
看點(diǎn)
02
優(yōu)化動(dòng)力主要來(lái)源
1)很多優(yōu)化都是來(lái)自于測(cè)試部提交的bug
2)用戶使用過(guò)程中反應(yīng)的各種問(wèn)題.
首先大家要明白現(xiàn)在開(kāi)發(fā)webAPP 有哪幾種方式及主流框架是什么,這里再給大家總結(jié)一下:
看點(diǎn)
03
開(kāi)發(fā)webAPP 有哪幾種方式
?3.1 單頁(yè)web應(yīng)用,如ExtJS,Backbone销钝,AngularJS,Avalon等
?3.2 基于框架webAPP,如Ionic,React Native,MUI等
那么這兩者有什么區(qū)別,又有什么優(yōu)勢(shì)呢?下面給那大家詳細(xì)介紹:
3.1 單頁(yè)web應(yīng)用
3.1.1單頁(yè)應(yīng)用現(xiàn)狀
單頁(yè)應(yīng)用的流行程度正在逐漸增加酱固,大家如果關(guān)注了一些初創(chuàng)型互聯(lián)網(wǎng)企業(yè)械念,會(huì)發(fā)現(xiàn)其中很大一部分的產(chǎn)品模式是單頁(yè)化的。這種模式能帶給用戶流暢的體驗(yàn)运悲,在開(kāi)發(fā)階段龄减,對(duì)JavaScript技能水平要求就比較高。
單頁(yè)應(yīng)用開(kāi)發(fā)過(guò)程中班眯,前后端是天然分離的欺殿,雙方以API為分界。前端作為服務(wù)的消費(fèi)者鳖敷,后端作為服務(wù)的提供者脖苏。在此模式下,前端將會(huì)推動(dòng)后端的服務(wù)化定踱。當(dāng)后端不再承擔(dān)模板渲染棍潘、輸出頁(yè)面這樣工作的情況下,它可以更專注于所提供的API的實(shí)現(xiàn)崖媚,而在這樣的情況下亦歉,Web前端與各種移動(dòng)終端的地位對(duì)等,也逐漸使得后端API不必再為每個(gè)端作差異化設(shè)計(jì)了畅哑。
3.1.2其中部署上也存在這很大的差異
現(xiàn)在越來(lái)呈現(xiàn)一種“無(wú)后端”的Web應(yīng)用肴楷。那么這又是什么呢??
說(shuō)的是你的產(chǎn)品很可能只需要自己編寫(xiě)靜態(tài)Web頁(yè)面,在某種云平臺(tái)上定制服務(wù)端API和云存儲(chǔ)荠呐,集成這個(gè)平臺(tái)提供的SDK赛蔫,通過(guò)AJAX等方式與之打交道,實(shí)現(xiàn)注冊(cè)認(rèn)證泥张、社交呵恢、消息推送、實(shí)時(shí)通信媚创、云存儲(chǔ)等功能渗钉。
我們仔細(xì)觀察這種模式就會(huì)發(fā)現(xiàn)該前后端已經(jīng)完全分離,前端代碼完全靜態(tài)化,這樣我們完全可以把它們放置到CDN上钞钙,這樣訪問(wèn)將大大地加速鳄橘,而服務(wù)端托管在云平臺(tái)上声离,開(kāi)發(fā)者也不必去關(guān)注一些部署方面的繁瑣細(xì)節(jié)。
假如你是一名創(chuàng)業(yè)者,同時(shí)也在做一款實(shí)時(shí)協(xié)同的單頁(yè)產(chǎn)品瘫怜,可以在云平臺(tái)上术徊,快速定制后端服務(wù),把絕大部分寶貴的時(shí)間花在開(kāi)發(fā)產(chǎn)品本身上宝磨。這樣就更加高效,更加的節(jié)省時(shí)間.
但是它也是有局限的?那么有哪些局限呢?
3.1.3 單頁(yè)web局限性
1)單頁(yè)應(yīng)用最根本的缺陷就是不利于SEO弧关,因?yàn)榻缑娴慕^大部分都是動(dòng)態(tài)生成的盅安,所以搜索引擎很不容易索引它?
2)用JS渲染的單頁(yè)面應(yīng)用性能相對(duì)比較差
首先我們來(lái)看看瀏覽器渲染機(jī)制:
渲染的步驟:
瀏覽器通過(guò)網(wǎng)絡(luò)請(qǐng)求加載頁(yè)面資源唤锉,在頁(yè)面呈現(xiàn)之前無(wú)論如何都要經(jīng)歷以下過(guò)程:
1)HTML→DOM?
2)CSS→CSSOM?
3)DOM + CSSOM → Render Tree?
4)對(duì)Render Tree進(jìn)行布局計(jì)算(Layout)?
5) 對(duì)布局結(jié)果進(jìn)行屏幕繪制(Paint)
整個(gè)過(guò)程都是相對(duì)比較耗時(shí)的,從而造成性能相對(duì)比較差
3.1.3對(duì)程序員掌握J(rèn)S語(yǔ)言程度
一個(gè)產(chǎn)品想要單頁(yè)化,首先是它必須適合單頁(yè)的形態(tài)别瞭。其次窿祥,在這個(gè)過(guò)程中,對(duì)開(kāi)發(fā)模式會(huì)產(chǎn)生一些變更蝙寨,對(duì)開(kāi)發(fā)技能也會(huì)有一些要求晒衩。?
開(kāi)發(fā)者的JavaScript技能必須過(guò)關(guān),同時(shí)需要對(duì)組件化墙歪、設(shè)計(jì)模式有所認(rèn)識(shí)听系,它所面對(duì)的不再是一個(gè)簡(jiǎn)單的頁(yè)面,而是一個(gè)運(yùn)行在瀏覽器環(huán)境中的桌面軟件虹菲。
3.2 基于框架webAPP
基于框架的webAPP 就比較常見(jiàn)的,如果大家還有不懂得,請(qǐng)參考博客中一篇文章.?
[框架之談]極佳的 JS 移動(dòng)應(yīng)用程序開(kāi)發(fā)框架?
這里不再講述了.下面著重給大家總結(jié)一下在開(kāi)發(fā)webAPP 中我們應(yīng)該注意什么?
看點(diǎn)
04
webAPP優(yōu)化方案
前端優(yōu)化分為兩個(gè)切入點(diǎn):網(wǎng)絡(luò)傳輸與DOM操作靠胜,而網(wǎng)絡(luò)傳輸是制約一個(gè)網(wǎng)站速度的主要因素。?
webAPP 優(yōu)化主要從以下幾個(gè)方面去著手:
4.1 網(wǎng)絡(luò)傳輸優(yōu)化?
4.2 DOM操作優(yōu)化?
4.3 內(nèi)存資源優(yōu)化?
4.4 其他優(yōu)化?
4.5 增強(qiáng)用戶體驗(yàn)優(yōu)化
下面一一來(lái)看看各個(gè)部分:
4.1 網(wǎng)絡(luò)傳輸優(yōu)化
4.1.1 網(wǎng)絡(luò)傳輸?shù)膬?yōu)化要點(diǎn)
零請(qǐng)求毕源,無(wú)流量其實(shí)說(shuō)白的就是最大程度的減少請(qǐng)求數(shù)浪漠,降低請(qǐng)求量。
4.1.2 首屏加速
然而對(duì)webapp模式的應(yīng)用來(lái)說(shuō)霎褐,首屏加載慢是一個(gè)不可避免的問(wèn)題址愿,所以提升webapp首屏加載速度是提升整體網(wǎng)站速度的關(guān)鍵。?
現(xiàn)在我們來(lái)看看網(wǎng)站首頁(yè)加載時(shí)間,現(xiàn)在我們分別取其150kb與30kb網(wǎng)速的加載速度冻璃,可以看出會(huì)慢响谓!?
如果是webAPP ,我們可以做以下的優(yōu)化:
1)我們應(yīng)該避免頁(yè)面長(zhǎng)時(shí)間白頁(yè),這個(gè)時(shí)候便提出了fake頁(yè)的概念省艳。頁(yè)面渲染只需要完整的HTML以及CSS歌粥,這個(gè)便是第一個(gè)優(yōu)化點(diǎn)。
2)從數(shù)據(jù)請(qǐng)求數(shù)以及請(qǐng)求量來(lái)說(shuō)拍埠,webapp首頁(yè)的響應(yīng)應(yīng)該比較慢失驶,若是任由js加載完成再渲染頁(yè)面,用戶很有可能失去耐心枣购。
3)但是從DOMContentLoaded來(lái)看嬉探,首頁(yè)事實(shí)上頁(yè)面響應(yīng)比較迅速擦耀,所以這個(gè)加載結(jié)束后頁(yè)面第一屏便渲染結(jié)束,然后再異步加載js涩堤,當(dāng)js改變后再動(dòng)態(tài)改變dom結(jié)構(gòu)中的一些關(guān)鍵點(diǎn)
這個(gè)時(shí)候一個(gè)靜態(tài)HTML頁(yè)面眷蜓,裝載首屏的基本內(nèi)容,讓首頁(yè)快速顯示,然后js加載結(jié)束后會(huì)馬上重新渲染整個(gè)頁(yè)面胎围,這個(gè)樣子吁系,用戶就可以很快的看到頁(yè)面響應(yīng),給用戶一個(gè)快的錯(cuò)覺(jué)白魂,給人感覺(jué)快得多汽纤。
4.1.3 降低請(qǐng)求數(shù)量
由webapp首頁(yè)來(lái)說(shuō),不可避免的使用的js文件較多福荸,這些文件分為兩類:?
① 框架js-css?
② 各個(gè)業(yè)務(wù)團(tuán)隊(duì)js-css?
所以可以限定每個(gè)業(yè)務(wù)團(tuán)隊(duì)只會(huì)加載這四個(gè)文件蕴坪,以最小降低請(qǐng)求數(shù),這里又涉及到并行加載敬锐,數(shù)量與容量有一個(gè)臨界值背传,如何取這個(gè)臨界值需要各位自己去實(shí)驗(yàn)
4.1.4 降低請(qǐng)求量
雖說(shuō)圖片壓縮是不必說(shuō)的事情,但是總會(huì)有些時(shí)候你會(huì)發(fā)現(xiàn)一些網(wǎng)站的圖片尺寸很大台夺,這個(gè)需要處理径玖,而且必須處理。
以框架庫(kù)為例颤介,除了核心包以外梳星,不需要的UI或者功能庫(kù)可以剔除,用到了再動(dòng)態(tài)加載买窟,減少首次加載量丰泊,這個(gè)一開(kāi)始就得做好,做不好后期就不好改
以業(yè)務(wù)團(tuán)隊(duì)為例始绍,首次加載的js與html模板會(huì)將常用的幾個(gè)頁(yè)面壓縮合并瞳购,其它頁(yè)面訪問(wèn)時(shí)再請(qǐng)求,若是想提升首屏加載便可以只下載需要的頁(yè)面文件亏推。
需要注意:
① 若是你們是要的還是jQuery庫(kù)的話学赛,可以考慮換成zepto了?
② 勿胡亂引用第三方庫(kù),若是要引用一定是讀懂源碼的情況下重寫(xiě)使用之吞杭,這樣的好處是盏浇,吃得透,萬(wàn)一有問(wèn)題芽狗,能改绢掰,而不是沒(méi)辦法又換庫(kù)
4.1.5緩存Ajax/localstorage
該方案的原理與前面類似,我們發(fā)送Ajax請(qǐng)求時(shí)候,應(yīng)該緩存一些非實(shí)時(shí)數(shù)據(jù)滴劲,比如城市信息和常用聯(lián)系人攻晒,但是我們只能緩存非敏感信息,?
產(chǎn)品搜索頁(yè)至列表頁(yè)的請(qǐng)求數(shù)據(jù)會(huì)緩存30s-60s班挖,若是過(guò)期時(shí)間內(nèi)用戶回到列表頁(yè)的話不會(huì)重新請(qǐng)求數(shù)據(jù)?
這對(duì)服務(wù)器壓力鲁捏,頁(yè)面響應(yīng)皆是有利的,這個(gè)在30s內(nèi)事實(shí)上意義不大萧芙,可以減少一次請(qǐng)求给梅。?
另外,對(duì)于get和post的效率双揪,曾經(jīng)有人做過(guò)一次測(cè)試:?
get100次平均耗時(shí)323ms动羽;post100次平均耗時(shí)589ms,所以post方式是比get慢的盟榴,但post請(qǐng)求的優(yōu)點(diǎn)是安全曹质,并且參數(shù)沒(méi)有長(zhǎng)度限制婴噩。
是選擇post還是選擇get擎场,皆需要處理,避免截?cái)鄒rl几莽,或者處處post迅办。-
4.1.6 lazyload懶加載
只顯示首屏頁(yè)面,其它內(nèi)容需要時(shí)再加載章蚣,比如列表頁(yè)站欺、圖片lazyload,皆需要做
4.2 DOM操作優(yōu)化方案
DOM操作主要分為頁(yè)面渲染與資源清理(heap控制)纤垂,兩者之間又相輔相成矾策,若是DOM操作一塊處理不好,其產(chǎn)生的感覺(jué)就不再是慢峭沦,而是卡,所以DOM操作優(yōu)化的主要目的就是消滅頁(yè)面卡的問(wèn)題贾虽,這個(gè)在移動(dòng)端尤為重要。
4.2.1 頁(yè)面渲染
瀏覽器會(huì)解析三個(gè)東西:HTML吼鱼、Javascript蓬豁、CSS?
瀏覽器首先會(huì)根據(jù)HTML生成DOM Tree,其次會(huì)根據(jù)CSS生成CSS Rule Tree菇肃,javascript可以通過(guò)DOM API與CSS API操作DOM Tree與CSS Rule Tree地粪,從而引起頁(yè)面變化。?
瀏覽器解析結(jié)束會(huì)通過(guò)DOM Tree與CSS Rule Tree形成render tree琐谤,只有display不為none的元素才會(huì)形成render Tree蟆技,render Tree形成后瀏覽器會(huì)調(diào)用GUI繪制頁(yè)面,在此之前做的一件事情便是layout或者說(shuō)reflow。上面的描述簡(jiǎn)單而言可以分為以下流程:
1)HTML→DOM?
2)CSS→CSSOM?
3)DOM + CSSOM → Render Tree?
4)對(duì)Render Tree進(jìn)行布局計(jì)算(Layout)?
5) 對(duì)布局結(jié)果進(jìn)行屏幕繪制(Paint)
在這個(gè)過(guò)程中质礼,若是javascript動(dòng)態(tài)改變DOM Tree便會(huì)引起reflow?
頁(yè)面中的元素改變聊品,只要不影響尺寸,比如只是顏色改變只會(huì)引起repaint不會(huì)引起回流.否則几苍,reflow不可避免翻屈,這個(gè)時(shí)候便需要重新計(jì)算形成render Tree,reflow分為局部回流與全局回流,會(huì)影響下面的妻坝,不會(huì)影響上面的元素.?
reflow耗用的系統(tǒng)資源較大伸眶,DOM Tree中受到影響的節(jié)點(diǎn)皆會(huì)reflow,然后影響其子節(jié)點(diǎn)最壞的情況是所有節(jié)點(diǎn)reflow刽宪,該問(wèn)題引發(fā)的現(xiàn)象便是低性能的電腦風(fēng)扇不停的轉(zhuǎn)厘贼,手機(jī)變得很熱,并且非常耗電圣拄,以下操作可能引起reflow
l) 操作dom結(jié)構(gòu)?
2) 動(dòng)畫(huà)?
3)DOM樣式修改?
4)獲取元素尺寸的API
4.2.2 減少使用定位屬性(fixed/absolute)
static元素處于文檔流中嘴秸,其渲染速度是最快的,我們做過(guò)一個(gè)測(cè)試:?
100個(gè)absolute元素與100個(gè)static元素渲染時(shí)差在0.01-0.007ms?
100000個(gè)元素渲染差距便增至30ms左右庇谆,這個(gè)微小的時(shí)差在移動(dòng)端變得尤為明顯岳掐,比如:?
小米/三星手機(jī)(1000左右),便存在明顯的渲染問(wèn)題饭耳,具體表現(xiàn)為:
l)定位元素在手機(jī)上不能顯示串述。?
2)定位元素動(dòng)畫(huà)效果失效。
以上問(wèn)題便是UI渲染失效多導(dǎo)致寞肖,最好的解決方案是減少使用定位元素纲酗,否則只能引起強(qiáng)烈reflow才能解決。?
另外新蟆,產(chǎn)品經(jīng)常會(huì)有fixed的相關(guān)需求觅赊,比如支付按鈕一直出現(xiàn)在低端,這個(gè)需求會(huì)造成兩個(gè)問(wèn)題:
l)fixed元素遭遇文本框時(shí)失效琼稻,可能會(huì)飄到頁(yè)面中間阻擋輸入?
2)影響效率
問(wèn)題一原因與移動(dòng)端的實(shí)現(xiàn)有關(guān)吮螺,暫時(shí)沒(méi)有完美的解決方案,問(wèn)題二便與渲染直接關(guān)聯(lián),滾屏?xí)r欣簇,頁(yè)面上所有的像素會(huì)跟著滾動(dòng)规脸,顯卡對(duì)全屏幕上下移動(dòng)的處理很快,但是若是出現(xiàn)一個(gè)fixed元素或者有元素不跟著一起滾動(dòng)熊咽,那么滾動(dòng)對(duì)手機(jī)瀏覽器來(lái)說(shuō)就是一個(gè)負(fù)擔(dān)莫鸭,這種滾動(dòng)的性能甚至體現(xiàn)在了iphone 4s,因?yàn)闈L動(dòng)可能會(huì)造成reflow横殴,這個(gè)現(xiàn)象體現(xiàn)在:
使用absolute配合javascript模擬fixed效果時(shí)被因,會(huì)有斷片的效果卿拴,該問(wèn)題在iphone5s便不會(huì)出現(xiàn)這個(gè)問(wèn)題。
4.3 其它優(yōu)化
當(dāng)然梨与,我們不能忽略產(chǎn)品的需求堕花,fixed類需求應(yīng)該在技術(shù)上得到解決,還用戶一個(gè)良好的體驗(yàn)粥鞋。
4.3.1 虛擬鍵盤(pán)導(dǎo)致fixed元素錯(cuò)位
fixed元素一定會(huì)伴隨虛擬鍵盤(pán)的出現(xiàn)缘挽,但是虛擬鍵盤(pán)只是“貼”在了viewport上,表面上不會(huì)對(duì)dom產(chǎn)生“任何”影響呻粹,但是這個(gè)時(shí)候fixed元素表現(xiàn)卻變得怪異起來(lái)壕曼,會(huì)錯(cuò)位。
應(yīng)用層面解決問(wèn)題方案是等浊,虛擬鍵盤(pán)彈出時(shí)將fixed元素設(shè)置為static腮郊,虛擬鍵盤(pán)消失時(shí)候設(shè)置回來(lái)。
由于虛擬鍵盤(pán)出現(xiàn)并未拋出事件筹燕,而檢測(cè)scroll或者resize事件轧飞,皆會(huì)有一定延遲,會(huì)出現(xiàn)閃爍現(xiàn)象撒踪,所以現(xiàn)有最好的方案是setinterval定時(shí)器監(jiān)控當(dāng)前獲取焦點(diǎn)元素是否為文本元素过咬,若是是的話便需要處理,如此便可解決fixed元素錯(cuò)誤問(wèn)題糠涛。
4.3.2 fixed元素滑動(dòng)慣性平滑度
我們常常遇到這種產(chǎn)品需求援奢,tab標(biāo)簽欄開(kāi)始固定兼犯,當(dāng)滾動(dòng)向下超過(guò)該標(biāo)簽欄后便會(huì)變成fixed元素忍捡,一直出現(xiàn)在頭部,這樣的需求在電腦上沒(méi)有問(wèn)題切黔,但是在iPhone5s以下的手機(jī)常常會(huì)出現(xiàn)小范圍錯(cuò)位或者快速移動(dòng)大范圍錯(cuò)位的問(wèn)題砸脊。
這個(gè)時(shí)候我們可以引起reflow迫使瀏覽器重繪以解決這個(gè)問(wèn)題,這里推薦一個(gè)奇怪的hack寫(xiě)法:同時(shí)設(shè)置三個(gè)image元素的src屬性纬霞,便可以全范圍解決該難題凌埂, 該方案被團(tuán)隊(duì)證實(shí)并得到應(yīng)用。
//三圖片src诗芜,引發(fā)reflow瞳抓,處理fixed方案慣性問(wèn)題
4.3.3 其它
l)CSS選擇器盡量使用id與class,避免過(guò)度層疊?
2)避免使用數(shù)值伏恐,比如:border: none不會(huì)引起渲染孩哑,而boder: 0會(huì)?
3)動(dòng)畫(huà)時(shí)候讓元素脫離文檔流,以免導(dǎo)致大量reflow?
4)避免逐條修改DOM樣式翠桦,改以className實(shí)現(xiàn)同樣功能?
5)操作DOM時(shí)將display設(shè)置為none横蜒,因?yàn)檫@種元素不會(huì)影響渲染,或者操作fragment對(duì)象取代操作顯示在頁(yè)面上的DOM?
6)避免將獲取DOM樣式屬性的操作寫(xiě)在循環(huán)中,可能引起重復(fù)reflow
4.4 內(nèi)存資源優(yōu)化
4.4.1 移動(dòng)端的javascript
首先丛晌,移動(dòng)端的性能與PC端的性能完全不在一個(gè)數(shù)量級(jí)上仅炊,比如,我哥做過(guò)一個(gè)測(cè)試澎蛛,使用innerHTML繪制大段抚垄,之后想獲取HTML的ID節(jié)點(diǎn),事實(shí)上是獲取不到的谋逻,這種問(wèn)題在單頁(yè)模擬多頁(yè)督勺,動(dòng)態(tài)創(chuàng)建DOM會(huì)經(jīng)常發(fā)生
這類問(wèn)題匪夷所思,因?yàn)轫?yè)面UI渲染與DOM操作是互斥的斤贰,但是就算出現(xiàn)了這個(gè)問(wèn)題智哀,一個(gè)解決方案是使用settimeout,更好的方案是使用DOMNodeRemoved事件監(jiān)控頁(yè)面DOM改變荧恍,將我們的DOM操作回調(diào)放入以確保渲染結(jié)束瓷叫。
以上問(wèn)題只是為了說(shuō)明移動(dòng)端的性能問(wèn)題,這類性能問(wèn)題會(huì)導(dǎo)致很多莫名其妙的問(wèn)題送巡,而且很多與渲染有關(guān)摹菠。但是這也從側(cè)面說(shuō)明了移動(dòng)端資源的緊缺,若是heap值過(guò)大骗爆,會(huì)導(dǎo)致操作出現(xiàn)卡的現(xiàn)象次氨,更有甚者,會(huì)引起頁(yè)面假死直接退出摘投。
webapp的模式煮寡,完全依賴于瀏覽器的垃圾回收,基本就是作死犀呼,因?yàn)閭鹘y(tǒng)頁(yè)面一旦刷新頁(yè)面整個(gè)資源完全釋放幸撕,而webapp沒(méi)有刷新這類操作,只有一個(gè)狀態(tài)到兩一個(gè)狀態(tài)外臂,不相關(guān)的內(nèi)存會(huì)保留坐儿,資源必須手動(dòng)釋放,或者說(shuō)宋光,框架必須提供垃圾釋放的機(jī)制貌矿。
這個(gè)由圖表heap值變化可以清晰看出。
而view切換過(guò)程中罪佳,不用的資源若是不手動(dòng)設(shè)置為null會(huì)導(dǎo)致變量得不到回收便脫離框架控制而失控了逛漫。
所以我們?cè)趙ebapp的過(guò)程中需要注意:
l) 釋放沒(méi)有使用的閉包?
2)觀察者需要得到清理?
3) 釋放定時(shí)器?
4)view切換過(guò)程中,在destroy中釋放view相關(guān)資源
4.4.2 閉包陷阱
在我們工作過(guò)程中菇民,濫用局部變量極有可能引起閉包陷阱尽楔,這個(gè)問(wèn)題不止是性能問(wèn)題投储,在邏輯上會(huì)引起錯(cuò)誤,而且不易發(fā)現(xiàn)阔馋,比如玛荞,在AMD閉包中使用一個(gè)局部變量
如此操作,會(huì)改變_ attributes對(duì)象呕寝,若是一個(gè)實(shí)例還無(wú)問(wèn)題勋眯,但是兩個(gè)實(shí)例的話便會(huì)發(fā)生變量污染。?
這只是一個(gè)例子下梢,但是在代碼中濫用局部變量可能會(huì)引起不必要的隱憂客蹋,戒之慎之。
4.4.3 webapp資源釋放
根據(jù)前面的描述孽江,我們可以得出一個(gè)結(jié)論:?
無(wú)論是view還是UI組件我們得提供統(tǒng)一的destroy接口讶坯,以便讓用戶繼承釋放資源。
若是view的資源得不到釋放導(dǎo)致heap值過(guò)高岗屏,webapp模式的網(wǎng)站其價(jià)值大減辆琅。
這里有幾點(diǎn)可以考慮:
1)webapp中view實(shí)例保存不超過(guò)5個(gè),多了便釋放dom結(jié)構(gòu)以及內(nèi)存引用(臨界值自己判斷最優(yōu))?
2)view隱藏時(shí)釋放內(nèi)部資源这刷,解除DOM事件句柄?
3) UI組件與view相同婉烟,需要統(tǒng)一釋放機(jī)制
但是單頁(yè)應(yīng)用由于頁(yè)面不會(huì)刷新,總有一些資源得不到釋放暇屋,此問(wèn)題任重道遠(yuǎn)
平時(shí)編寫(xiě)過(guò)程可以做以下優(yōu)化:
1) 使用函數(shù)替換邏輯
讓我們的函數(shù)產(chǎn)生一個(gè)返回值替換函數(shù)中的大段邏輯似袁,這樣的第一個(gè)好處便是邏輯清晰,第二個(gè)好處是這些函數(shù)在不同的函數(shù)中咐刨,這個(gè)函數(shù)被使用后便會(huì)自動(dòng)得到釋放昙衅。
2) 清理閉包引用
當(dāng)一個(gè)閉包函數(shù)或者什么使用結(jié)束后,若不會(huì)再使用所宰,便需要手動(dòng)清理該變量绒尊,以便解除閉包之間的引用關(guān)系,從而釋放資源仔粥。
3) 使用對(duì)象屬性或者方法
一個(gè)對(duì)象可以引用其他對(duì)象的屬性或者方法,比如obj.foo = thatObj;這種情況下蟹但,我們可以隨時(shí)刪除對(duì)象解除引用關(guān)系躯泰,然后便可以清理資源。
4.4.4 動(dòng)畫(huà)與假死
動(dòng)畫(huà)而言建議采用CSS3實(shí)現(xiàn)動(dòng)畫(huà)华糖,CSS3中又推薦采用最新的接口麦向,比如使用transform取代top/lelf操作,這樣操作效率搞得多客叉。
若是采用動(dòng)畫(huà)可以將對(duì)應(yīng)元素設(shè)置為absolute以減少回流诵竭,另外最關(guān)鍵一點(diǎn)還是避免移動(dòng)DOM樹(shù)過(guò)多的節(jié)點(diǎn)话告,這個(gè)時(shí)候需要駁回產(chǎn)品無(wú)理需求,比如:
產(chǎn)品要求日期滾屏組件卵慰,顯示半年的數(shù)據(jù)沙郭,這半年的數(shù)據(jù)便是180個(gè)DOM樹(shù)
這個(gè)級(jí)別的DOM一旦移動(dòng)整個(gè)手機(jī)會(huì)直接卡死,甚至構(gòu)建DOM樹(shù)裳朋,渲染頁(yè)面也會(huì)出現(xiàn)假死現(xiàn)象病线,該問(wèn)題需要規(guī)避。
4.4.5 Application Cache
Application Cache是HTML5為webapp離線使用而增加的API鲤嫡,與localstorage送挑、cookie等不同,Application Cache存儲(chǔ)的是一系列請(qǐng)求資源允許瀏覽器在請(qǐng)求資源時(shí)不必通過(guò)網(wǎng)絡(luò)暖眼,設(shè)計(jì)得當(dāng)?shù)脑捒梢詫?shí)現(xiàn)離線應(yīng)用惕耕。?
使用Application Cache主要是在網(wǎng)絡(luò)性能上提升,有效降低了網(wǎng)絡(luò)延遲诫肠,提升請(qǐng)求加速.
4.5 用戶體驗(yàn)優(yōu)化
4.5.1 區(qū)域滾動(dòng)
就官方的例子便會(huì)出現(xiàn)以下問(wèn)題:
1)頭部消失
2)偶爾不能顯示文本框焦點(diǎn)赡突,或者焦點(diǎn)錯(cuò)位
若是以上問(wèn)題可忽略,但是文本框不見(jiàn)了這種事情区赵,我是不會(huì)接受的
導(dǎo)致的原因與組織瀏覽器默認(rèn)事件有關(guān)惭缰,所以,我這里不太推薦各位大范圍的使用區(qū)域滾動(dòng)笼才,而改在區(qū)域使用漱受,
就去哪兒的ipad版本在一個(gè)具有文本框的地方使用了IScroll,其提高的用戶體驗(yàn)與導(dǎo)致的問(wèn)題一樣引人入勝骡送。
事實(shí)上昂羡,小釵及其推崇IScroll庫(kù),雖說(shuō)他有這樣那樣問(wèn)題摔踱,但是虐先,IScroll是最有可能帶來(lái)移動(dòng)端革命的庫(kù),因?yàn)樗梢裕?/p>
① 解決webapp區(qū)域滾動(dòng)
② 變相解決fixed問(wèn)題
③ 解決動(dòng)畫(huà)過(guò)程帶來(lái)的長(zhǎng)短頁(yè)問(wèn)題
總而言之派敷,IScroll方案的提出蛹批,是讓webapp媲美native app靠近了一大步,真正的平起平坐還需要瀏覽器的支援
4.5.2 點(diǎn)擊響應(yīng)
click本身在移動(dòng)端響應(yīng)是沒(méi)有問(wèn)題的篮愉,但是我們點(diǎn)擊下來(lái)300ms 的延遲卻是事實(shí)腐芍,這種事實(shí)造成的原因就是?
手機(jī)需要知道你是不是想雙擊放大網(wǎng)頁(yè)內(nèi)容?
所以click點(diǎn)擊響應(yīng)慢,而touch卻不會(huì)有這樣的限制试躏,于是移動(dòng)端的touch相當(dāng)受歡迎猪勇,至于鼠標(biāo)慢,他究竟有多慢颠蕴,我會(huì)告訴你每次會(huì)慢300ms?