基于VUE的SPA單頁應(yīng)用開發(fā)-加載性能篇

1胀屿、基于異步數(shù)據(jù)的vue頁面刷新

先看看基于異步數(shù)據(jù)的vue頁面刷新后耍目,都發(fā)生了啥~

如圖所示:

圖1 基于異步數(shù)據(jù)的vue頁面刷新 網(wǎng)絡(luò)請(qǐng)求圖

步驟如下:

step1:請(qǐng)求頁面;

step2:請(qǐng)求頁面內(nèi)的css廓潜、js資源丽焊;

step3:vue頁面初始化妹窖;

step4:頁面渲染啊奄,框架呈現(xiàn)[無數(shù)據(jù)內(nèi)容]渐苏;

step5:請(qǐng)求頁面實(shí)際數(shù)據(jù);

step6:數(shù)據(jù)ready菇夸,填充視圖琼富,圖片資源加載;

step7:完整頁面呈現(xiàn)庄新。

步驟分析:

step1:請(qǐng)求html文件鞠眉;

step2:請(qǐng)求資源;

優(yōu)化點(diǎn):

a摄咆、多次訪問的資源緩存:可從MD5凡蚜、組件打包方式等角度再細(xì)分;

b人断、app框架資源預(yù)加載:如果是hybird開發(fā)的app吭从,可通過app框架預(yù)加載的方式,將單頁應(yīng)用的資源提前緩存恶迈。

單頁的css涩金、js資源,與傳統(tǒng)頁面的資源相比暇仲,規(guī)模要大很多步做。其集合了幾乎單頁應(yīng)用的所有css、js文件奈附,隨著應(yīng)用的規(guī)模大小成正比增長全度。合理的緩存處理,將大大提升頁面加載速度斥滤。a将鸵、b兩點(diǎn)可實(shí)現(xiàn)性能加速的原因是勉盅,本地加載過的資源,會(huì)緩存在本地顶掉;頁面請(qǐng)求資源時(shí)草娜,瀏覽器會(huì)先查找緩存,如果有緩存痒筒,則本地取宰闰,節(jié)省了網(wǎng)絡(luò)請(qǐng)求。[可了解瀏覽器的強(qiáng)緩簿透、弱緩]

step3:頁面初始化移袍;

優(yōu)化點(diǎn):

利用v-if指令按需加載組件~

由于vue在初始化過程中,會(huì)深度查找子組件老充,生成依賴咐容,構(gòu)建虛擬DOM,所以其初始化時(shí)間相對(duì)較長蚂维;不過在查找過程中戳粒,遇到v-if為false的組件,將停止深度查找虫啥,從而節(jié)省初始化時(shí)間蔚约。由此可通過控制v-if的布爾值,實(shí)現(xiàn)性能優(yōu)化和組件的按需加載涂籽。例如在初始化過程中苹祟,僅首屏必須的組件v-if=true,其他組件[如非首屏組件评雌、彈窗組件等]树枫,可在下一事件循環(huán)中[通過setTimeout(fn, 0)等異步操作可實(shí)現(xiàn)],或者首屏資源加載完成后景东,開啟砂轻。

step4:默認(rèn)數(shù)據(jù)頁面渲染;(默認(rèn)數(shù)據(jù)由vuex提供)

優(yōu)化點(diǎn):無數(shù)據(jù)的頁面框架的渲染展現(xiàn)[通常所說的灰框]斤吐,讓用戶提前感知頁面搔涝,從而提升用戶體驗(yàn);(包括讀取vuex數(shù)據(jù)和措,進(jìn)行渲染)

step5:異步請(qǐng)求數(shù)據(jù)庄呈,與step4同時(shí)進(jìn)行,通過ajax實(shí)現(xiàn)派阱;

step6:資源加載诬留;

優(yōu)化點(diǎn):進(jìn)行圖片[視頻]分批加載優(yōu)化,從而增加同一帶寬下單圖的加載速度,加速首屏展現(xiàn)文兑。

建議圖片加載流程:

step6-1:首屏展現(xiàn)必須圖片加載及首屏默認(rèn)圖片傀广;[如:banner圖第一張];

step6-2:首屏其余圖片加載及其他默認(rèn)圖片彩届;[如:剩余的banner圖]伪冰;

step6-3:非首屏 or 彈窗。[接下來的加載順序樟蠕,可根據(jù)需求調(diào)整贮聂。但要遵循一條原則,不影響首屏的用戶交互寨辩。]

2吓懈、基于異步數(shù)據(jù)的vue頁面的路由跳轉(zhuǎn)

再來看看通過單頁路由跳轉(zhuǎn)到新頁,又發(fā)生了什么靡狞?

圖2 基于異步數(shù)據(jù)的vue頁面路由跳轉(zhuǎn) 網(wǎng)絡(luò)請(qǐng)求圖

頁面加載步驟:

step1:捕獲到路由變化耻警;

step2:初始化該頁面,并默認(rèn)數(shù)據(jù)渲染甸怕;(包括讀取vuex數(shù)據(jù)甘穿,進(jìn)行渲染)[step3、step4]

step3:異步請(qǐng)求最新的初始化數(shù)據(jù)梢杭;[同step5]

step4:資源分批預(yù)加載温兼。[同step6]

總結(jié):

優(yōu)勢(shì):頁內(nèi)跳轉(zhuǎn)性能非常贊。對(duì)比圖1和圖2武契,在路由內(nèi)跳轉(zhuǎn)時(shí)減少了圖1中step1募判、step2的頁面請(qǐng)求和.css、.js的請(qǐng)求時(shí)間[節(jié)省1s+]咒唆,頁面展現(xiàn)嗖嗖的届垫。再好好結(jié)合vuex的數(shù)據(jù)流,可以給用戶非常棒的體驗(yàn)全释。

劣勢(shì):再觀察圖1的網(wǎng)絡(luò)請(qǐng)求圖装处,可以發(fā)現(xiàn)以下幾點(diǎn):

a、css恨溜、js資源相對(duì)傳統(tǒng)頁面符衔,量更大,加載時(shí)間加長糟袁;

b、vue的首屏展現(xiàn)躺盛,依賴異步數(shù)據(jù)的請(qǐng)求项戴,相對(duì)傳統(tǒng)同步頁面,增加了單獨(dú)的數(shù)據(jù)請(qǐng)求時(shí)間消耗槽惫;

c周叮、頁面渲染辩撑,在js執(zhí)行完畢之后,才開始進(jìn)行仿耽;而最終的首屏展現(xiàn)合冀,則需要等待異步數(shù)據(jù)請(qǐng)求到達(dá)之后。

由于a项贺、b的存在君躺,c的首屏展現(xiàn)時(shí)間相對(duì)傳統(tǒng)頁面更慢。

VUE的異步單頁應(yīng)用優(yōu)勢(shì)與劣勢(shì)非常明顯开缎,缺點(diǎn)是初始化時(shí)間長棕叫,依賴js資源的加載;優(yōu)勢(shì)是運(yùn)行速度快奕删,路由內(nèi)跳轉(zhuǎn)幾乎沒太多的時(shí)間消耗俺泣。如果是一定規(guī)模大小的單頁應(yīng)用,它將是不錯(cuò)的選擇完残。特別是使用hybird開發(fā)伏钠,通過app框架將資源預(yù)加載之后,需依賴js資源的劣勢(shì)也必將不存在谨设,那將給到用戶傳統(tǒng)頁面無法給到的體驗(yàn)贝润。

Q:那有什么辦法來解決這些劣勢(shì)嗎?

A:在接下來的3中铝宵,將提出一種解決方案打掘。

3、提速方案

對(duì)于a點(diǎn)鹏秋,資源量大尊蚁,可以從打包方式、緩存侣夷、CDN分發(fā)等角度進(jìn)行處理横朋;

對(duì)于b點(diǎn),有兩種方式解決:

1百拓、同步+異步數(shù)據(jù)請(qǐng)求:刷新頁面時(shí)琴锭,使用同步MVC框架的方式,通過后臺(tái)路由帶入初始化數(shù)據(jù)衙传;頁內(nèi)路由跳轉(zhuǎn)時(shí)决帖,仍然采用異步的方式進(jìn)行。

2蓖捶、異步數(shù)據(jù)請(qǐng)求提前:刷新頁面時(shí)地回,將數(shù)據(jù)請(qǐng)求提前至js資源加載前,由于網(wǎng)絡(luò)請(qǐng)求可并發(fā)多個(gè),將節(jié)省單獨(dú)的數(shù)據(jù)請(qǐng)求時(shí)間刻像。

tips:如果不是mvvm的異步單頁畅买,推薦使用同步+異步的方式,頁面的展現(xiàn)可以提前至js資源加載之前细睡。[由于mvvm框架下的頁面視圖通過數(shù)據(jù)進(jìn)行驅(qū)動(dòng)谷羞,該驅(qū)動(dòng)的基本需要依賴js腳本實(shí)現(xiàn),所以必須等待js加載完畢溜徙,才能正確展現(xiàn)頁面湃缎。因此,在mvvm框架下萌京,同步+異步的方式僅能節(jié)省數(shù)據(jù)請(qǐng)求時(shí)間雁歌,但其他單頁應(yīng)用可以節(jié)省數(shù)據(jù)請(qǐng)求時(shí)間+js資源加載時(shí)間]

ps:js的加載順序:不影響頁面初始化呈現(xiàn)的js底部后置:如日志、分享知残、im的相關(guān)js靠瞎。

4、初始化性能優(yōu)化[可用于加速首屏呈現(xiàn)]

如下示例:

其頁面結(jié)構(gòu)與組件結(jié)構(gòu)關(guān)系圖如下:

vue初始化的組件編譯原則是求妹,按照深度查找乏盐,遇到v-if為false的節(jié)點(diǎn)或者葉子節(jié)點(diǎn),停止查找制恍。從示例的組件結(jié)構(gòu)圖父能,我們可以看出,

初始化中組件查找過程為:

step1:首先查找根節(jié)點(diǎn)的子組件nav組件净神,其為葉子節(jié)點(diǎn)何吝,編譯,返回鹃唯;

step2:查找app的第二個(gè)子組件(節(jié)點(diǎn))content爱榕,其非葉子節(jié)點(diǎn),且無v-if標(biāo)記坡慌,繼續(xù)深度查找黔酥;查找其子節(jié)點(diǎn)c-a組件,為葉子節(jié)點(diǎn)洪橘,編譯跪者,返回content;查找另一個(gè)子節(jié)點(diǎn)c-b組件熄求,葉子節(jié)點(diǎn)渣玲,編譯,返回抡四;

step3:節(jié)點(diǎn)content查找完畢柜蜈;返回app仗谆,查找sidebar節(jié)點(diǎn)指巡,sidebar非葉子節(jié)點(diǎn)淑履,且無v-if,繼續(xù)深度查找藻雪;同step2秘噪,最終返回app節(jié)點(diǎn)。

step4:所有組件編譯完畢勉耀,初始化完畢指煎,渲染。

如上示例便斥,將深度遍歷所有子組件至壤,再完成渲染。如果將首屏不需要展現(xiàn)的組件設(shè)置成v-if枢纠,將降低深度查找的復(fù)雜度像街,從而加速組件初始化,加速頁面的呈現(xiàn)晋渺。

加速代碼如下:

? ? ? ? ? ? newVue({? ? data: {? ? ? ? showContent:false,? ? ? ? showSidebar:false},? ? created () {//顯示content? ? ? ? setTimeout(()=>{this.showContent =true;? ? ? ? },0);//顯示sidebar? ? ? ? setTimeout(()=>{this.showSidebar =true;? ? ? ? },0);? ? }});

以上代碼將組件content與sidebar的v-if設(shè)置成false镰绎,組件的編譯查找過程如下:

step1:不變;

step2:查找content組件木西,其為v-if=false畴栖,停止,并返回根節(jié)點(diǎn)八千;

step3:查找sidebar組件吗讶,其為v-if=false,停止恋捆,并返回根節(jié)點(diǎn)照皆;

step4:所有組件編譯完畢,初始化完畢鸠信,渲染纵寝。

是不是快了很多~~由此,首先被渲染星立,出現(xiàn)的是nav組件結(jié)構(gòu)爽茴;另外兩個(gè)組件通過showContent,showSidebar控制绰垂。

為何這里使用setTimeout(fn, 0)控制兩個(gè)組件的狀態(tài)變化呢室奏?

因?yàn)閟etTimeout是時(shí)間異步處理模塊,通過其設(shè)置劲装,相應(yīng)的處理方法將在下一事件循環(huán)中才被執(zhí)行胧沫,而VUE的渲染時(shí)機(jī)為本次主線程執(zhí)行完畢昌简。如此,使得另外兩個(gè)組件的編譯推遲到首次渲染之后绒怨,從而實(shí)現(xiàn)組件加速纯赎。

tips:這里需要注意,不是將組件設(shè)置v-if=false就可以了南蹂,要看看v-if=true的開啟時(shí)機(jī)犬金,如果是同一事件循環(huán)中被開啟,便沒有意義了六剥。因?yàn)関ue的數(shù)據(jù)驅(qū)動(dòng)渲染時(shí)機(jī)晚顷,是同一事件循環(huán)中的代碼全部執(zhí)行完畢之后,拿到數(shù)據(jù)的最終狀態(tài)才進(jìn)行疗疟。同時(shí)该默,setTimeout(fn, 0)也不可亂用。

附加:圖片分批預(yù)加載的js腳本

參數(shù)說明:

auto: 是否自執(zhí)行

imgs: 需預(yù)加載的圖片列表策彤,為二維表

ignore:在自執(zhí)行過程中栓袖,需要跳過的圖片批次腳標(biāo)

firstSetReady: 第一組圖片完成加載以后,置為true锅锨,便于外部掌握狀態(tài)[一般首屏資源為第一組圖片]

finished: 所有圖片資源加載完畢

說明:

非自執(zhí)行的需求叽赊,可直接調(diào)用loadOneSetImages方法,返回值為promise

letco =require('co')classPreload{// 定義構(gòu)造函數(shù)的數(shù)據(jù)結(jié)構(gòu)必搞,創(chuàng)建實(shí)例對(duì)象時(shí)必指,自動(dòng)初始化constructor(auto, imgs = [], ignore = []) {this.imgs = imgs;this.ignore = ignore;this.auto = auto;this.firstSetReady =false;this.finished =false;this.init();? ? }// 初始化函數(shù)init() {letme =this// 如果自動(dòng)執(zhí)行,則調(diào)用co模塊恕洲,自動(dòng)加載資源if(this.auto) {// generator的自執(zhí)行函數(shù)塔橡,資源加載完畢時(shí),參數(shù)finished置為trueco(this.autoExeImageStream.call(this)).then(function(){console.log('資源加載完畢~')? ? ? ? ? ? ? ? me.finished =true}).catch(function(){console.log('資源加載出錯(cuò)~')? ? ? ? ? ? ? ? me.finished =true})? ? ? ? }? ? }// 同步加載分批圖片資源霜第,使用generator函數(shù)葛家,完成當(dāng)前批次加載,再啟動(dòng)下一批次的加載* autoExeImageStream() {letrstList = []for(leti =0; i

圖片分批預(yù)加載腳本通過ES6 promise結(jié)合generator函數(shù)實(shí)現(xiàn)泌类,使得圖片按照我們想要的方式順序加載癞谒,且單批次速度更快。但不能濫用刃榨,需要留意圖片資源的加載規(guī)模與用戶交互操作之間的關(guān)系弹砚。由于,ES6 的 promise在事件循環(huán)中的消息處理級(jí)別高于DOM事件[or 網(wǎng)絡(luò)請(qǐng)求等其他異步模塊]枢希,當(dāng)有 promise 消息要處理時(shí)桌吃,其他事件消息將等待,直到promise處理完畢苞轿。因此在使用其進(jìn)行預(yù)加載時(shí)茅诱,一定要結(jié)合業(yè)務(wù)情況及預(yù)加載的需求進(jìn)行設(shè)置逗物。如有需要可以創(chuàng)建多個(gè)preload實(shí)例,通過一定的條件瑟俭,觸發(fā)圖片預(yù)加載翎卓,將其進(jìn)行分散,從而達(dá)到性能加速的同時(shí)尔当,用戶交互體驗(yàn)也不受影響莲祸。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蹂安,一起剝皮案震驚了整個(gè)濱河市椭迎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌田盈,老刑警劉巖畜号,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異允瞧,居然都是意外死亡简软,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門述暂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痹升,“玉大人,你說我怎么就攤上這事畦韭√鄱辏” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵艺配,是天一觀的道長察郁。 經(jīng)常有香客問我,道長转唉,這世上最難降的妖魔是什么皮钠? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮赠法,結(jié)果婚禮上麦轰,老公的妹妹穿的比我還像新娘。我一直安慰自己砖织,他們只是感情好款侵,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著镶苞,像睡著了一般喳坠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茂蚓,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天壕鹉,我揣著相機(jī)與錄音剃幌,去河邊找鬼。 笑死晾浴,一個(gè)胖子當(dāng)著我的面吹牛负乡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播脊凰,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼抖棘,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了狸涌?” 一聲冷哼從身側(cè)響起切省,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帕胆,沒想到半個(gè)月后朝捆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡懒豹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年芙盘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脸秽。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡儒老,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出记餐,到底是詐尸還是另有隱情驮樊,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布剥扣,位于F島的核電站巩剖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏钠怯。R本人自食惡果不足惜佳魔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望晦炊。 院中可真熱鬧鞠鲜,春花似錦、人聲如沸断国。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稳衬。三九已至撵渡,卻和暖如春衡楞,著一層夾襖步出監(jiān)牢的瞬間歇僧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國打工赊琳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砰碴。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓躏筏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親呈枉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子趁尼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,280評(píng)論 25 707
  • 30余年的第一次出去旅行,第一次坐飛機(jī)猖辫,飛機(jī)飛起的那一刻我在想酥泞,兒子,你沒坐過飛機(jī)住册,下次媽媽一定帶你...
    傻傻的二丫頭閱讀 201評(píng)論 2 1