如何加快SPA的速度

單頁面應(yīng)用程序(SPA)可能要花很長時間才能發(fā)射汉矿。這是一個巨大的問題肯骇,因為即使延遲一秒鐘也會使您花費7%的轉(zhuǎn)化爽篷。

但是就像您可以使單頁應(yīng)用程序?qū)EO友好一樣毡庆,您也可以提高其性能显拜。

因此吃媒,這是我們的詳細指南瓤介,針對那些希望在2020年加速SPA應(yīng)用程序的人。對于那些不熟悉SPA概念的人赘那,我建議從我們的文章開始刑桑,內(nèi)容是什么是單頁應(yīng)用程序以及它們與傳統(tǒng)多頁應(yīng)用程序的比較頁應(yīng)用程序。

監(jiān)控您的SPA效果

有很多工具可以幫助您監(jiān)視SPA性能募舟。首先漾月,您可以使用Chrome Devtools擴展,例如Lighthouse胃珍,Ember InspectorReact Performance Devtools梁肿。

此類工具的問題在于它們不能反映出您的SPA的感知加載速度(這對用戶來說很重要)。

還有諸如速度索引之類的其他工具集觅彰,它們試圖匹配實際的用戶體驗吩蔑。

但是實際用戶來自各種各樣的設(shè)備/網(wǎng)絡(luò),因此很難在綜合測試環(huán)境中考慮所有這些因素填抬。

我們建議您使用真實用戶監(jiān)視(RUM)烛芬。它被動地跟蹤人們與您的應(yīng)用程序的每次交互,從而為您提供有關(guān)用戶如何感知其加載速度的準確實時圖像。

如果您喜歡現(xiàn)成的解決方案赘娄,那么這里是一些支持單頁應(yīng)用程序的RUM工具的簡短列表:

您還可以要求您的開發(fā)團隊將RUM應(yīng)用于SPA仆潮。

它必須識別連續(xù)導(dǎo)航的開始(又稱導(dǎo)航/頁面內(nèi)導(dǎo)航:應(yīng)用啟動后,用戶單擊指向SPA中新“頁面”的鏈接/按鈕)以及頁面完全被載入那一刻遣臼。已加載性置。開發(fā)人員可以通過幾種方式實現(xiàn)此目的:

  • 使用Resource Timing API識別何時進行AJAX調(diào)用以查明頁內(nèi)導(dǎo)航的開始;
  • 使用Mutation Observer可以檢測到對DOM的修改揍堰,并通過Resource Timing API識別網(wǎng)絡(luò)活動的結(jié)束鹏浅。

實踐表明,這些方法可能不可靠屏歹,并且結(jié)果不準確隐砸。例如,即使用戶不啟動頁內(nèi)導(dǎo)航蝙眶,您的SPA也會調(diào)用AJAX來預(yù)取一些數(shù)據(jù)季希。否則結(jié)果可能會因網(wǎng)絡(luò)活動而歪曲,而不會影響屏幕上發(fā)生的事情幽纷。

為了解決這個問題式塌,他們可以使用簡單的API來衡量加載時間:

var rumObj = new RumTracking({
  'web-ui-framework': 'EMBER'
});
 
// App Launch - window.performance.timing.navigationStart is the start marker
rumObj.setPageKey('feed_page_key');
// Do rendering
rumObj.appRenderComplete();
 
// Successive navigation
rumObj.appTransitionStart();
rumObj.setPageKey('profile_page_key');
// Do rendering
rumObj.appRenderComplete();

使用這種方法,每個頁面都必須編寫檢測代碼霹崎。

許多單頁應(yīng)用程序JavaScript框架都有生命周期hooks 珊搀,可用于自動執(zhí)行檢測冶忱。

// Add instrumentation for successive navigation start
router.on('willTransition', () => {
 a. rumObj.appTransitionStart();
});
 
// Add instrumentation for rendering is complete
router.on('didTransition', () => {
Ember.run.scheduleOnce('afterRender', () => {
 a. rumObj.appRenderComplete();
   });
});

因此尾菇,開發(fā)人員可以使用Navigation Timing API的導(dǎo)航開始來檢測初始導(dǎo)航的開始。路由器的willTransition事件將標志著頁面內(nèi)導(dǎo)航的開始囚枪。

通過監(jiān)聽еруdidTransition事件并在afterRender隊列中添加工作派诬,您將知道兩種模式下頁面的完全加載時間。

現(xiàn)在链沼,您已經(jīng)擁有測量加載時間所需的一切默赂。要發(fā)現(xiàn)性能瓶頸,您需要細分RUM數(shù)據(jù)括勺。您可以通過User Timing API檢測單個資源的加載時間缆八。

典型的SPA的性能瀑布外觀

現(xiàn)在是時候分析RUM數(shù)據(jù),看看可以如何解決瓶頸了疾捍。

改善SPA性能的六大方法

1.懶惰地呈現(xiàn)折疊式內(nèi)容

簡而言之奈辰,這意味著僅呈現(xiàn)頁面上當前對用戶可見的那些部分(即首屏內(nèi)容)。

如果您的SPA在渲染階段花費大量時間(請參見上圖)乱豆,則惰性渲染很有用奖恰。在此階段,應(yīng)用程序?qū)轫撁嫔系乃薪M件創(chuàng)建DOM(有關(guān)如何在頁面上表示文本,圖像和其他對象的規(guī)范)瑟啃。

一旦為首個組件構(gòu)建了DOM论泛,就可以產(chǎn)生瀏覽器的主線程。這將加快SPA的啟動速度蛹屿,因為您不必呈現(xiàn)當前不需要的資源屁奏。

將渲染優(yōu)先級分配給頁面上的所有組件可能會帶來另一個性能提升(因此瀏覽器不會同時渲染所有組件)。

這樣蜡峰,您可以加快“第一個有意義的畫圖”(即用戶看到頁面核心內(nèi)容的時間)了袁。通過不渲染某些不可見的組件,您還將改善“互動時間”湿颅。

2.使用延遲數(shù)據(jù)獲取

加快渲染階段之后载绿,您可能需要研究過渡階段。

此時油航,SPA加載數(shù)據(jù)崭庸,對其進行規(guī)范化并將其推送到存儲中。為了減少在此階段花費的時間谊囚,您需要減少SPA處理的數(shù)據(jù)量怕享。

正如您可以懶惰地呈現(xiàn)折疊式內(nèi)容一樣,您可以推遲加載數(shù)據(jù)镰踏,直到真正需要它為止函筋。

您可以使用一個高級調(diào)用來獲取“第一有意義繪畫”所需的數(shù)據(jù),而可以使用另一個調(diào)用來懶惰地加載頁面所需的其余數(shù)據(jù)奠伪。

注意:上述方法適用于啟動模式和頁內(nèi)導(dǎo)航跌帐,因為它們減少了前端時間。

一些SPA框架(例如React绊率,Angular或Vue)允許開發(fā)人員將應(yīng)用程序代碼分成幾個捆綁包谨敛。您可以同時或在必要時加載它們。第二個選項可以加快第一個導(dǎo)航的速度滤否。例如脸狸,您可以僅加載用戶可以立即訪問的部件,而推遲其他所有操作(例如藐俺,需要授權(quán)的部件)炊甲。

3.緩存靜態(tài)內(nèi)容

研究您的SPA,以確定何時可以在用戶設(shè)備上存儲圖像和其他靜態(tài)資源欲芹。

即使使用最佳服務(wù)器卿啡,從內(nèi)存或Web存儲中提取數(shù)據(jù)所需的時間也比發(fā)送HTTP請求少得多。

設(shè)備內(nèi)存比最快的網(wǎng)絡(luò)快得多耀石。因此牵囤,緩存是您最好的朋友爸黄。

對于大量集合,您可以使用某種分頁并依靠服務(wù)器來保持持久性揭鳞,或者編寫LRU算法來從存儲中擦除備用項炕贵。

您可以使用Service Worker在SPA中緩存靜態(tài)內(nèi)容。

它們是在后臺運行的客戶端腳本野崇。您可以使用它們來減少流量并啟用脫機功能称开。當瀏覽器請求內(nèi)容時,它首先經(jīng)過服務(wù)人員乓梨。如果請求的內(nèi)容存在于緩存中鳖轰,則服務(wù)工作者將檢索它并顯示在屏幕上。在其他情況下扶镀,它將從網(wǎng)絡(luò)請求資源蕴侣。

您還可以使用IndexedDB API緩存大量結(jié)構(gòu)化數(shù)據(jù)。

4.在適當?shù)牡胤绞褂肳ebSockets(即用于高度交互的應(yīng)用程序)

WebSocket是允許用戶瀏覽器和服務(wù)器之間進行雙向通信的協(xié)議臭觉。與HTTP不同昆雀,客戶端不必不斷向服務(wù)器發(fā)送請求以獲取新消息。取而代之的是蝠筑,瀏覽器僅偵聽服務(wù)器并在就緒時接收消息狞膘。

結(jié)果,您得到的連接在某些情況下可以比常規(guī)HTTP快400%什乙。

您可以使用socket.io之類的服務(wù)為SPA實現(xiàn)WebSockets挽封。

5.使用JSONP / CORS繞過同源策略

許多應(yīng)用程序的某些功能都依賴于第三方API。

但是由于同源策略臣镣,您無法對瀏覽器認為位于另一臺服務(wù)器上的頁面進行AJAX調(diào)用辅愿。要獲得對第三方API的訪問權(quán)限,該應(yīng)用將必須使用源服務(wù)器作為代理退疫。

額外的往返意味著更多的延遲渠缕。


如果不處理檢索到的數(shù)據(jù)并且不將其存儲在系統(tǒng)中鸽素,則可以直接請求資源褒繁。為此,您可以使用帶有填充的JSON(JSONP)或跨域資源共享(CORS)

JSON with Padding

JSONP充分利用了瀏覽器允許您添加來自其他域的<script>標簽的事實馍忽。通過JSONP請求棒坏,您可以動態(tài)構(gòu)造這些標簽,并將URL參數(shù)傳遞給必要的資源遭笋。

然后坝冕,標記會在JSON響應(yīng)中返回資源。

但是有一個缺點瓦呼。使用<script>標記時喂窟,JSONP僅適用于<GET>請求。您可以通過將async和defer屬性添加到外部腳本來進一步提高性能。如果沒有這些屬性磨澡,瀏覽器必須先下載并執(zhí)行腳本碗啄,然后才能顯示頁面的其余部分。

這減慢了感知的加載速度稳摄。

如果包含async屬性稚字,則瀏覽器在加載腳本時不會停止解析頁面,但是在執(zhí)行腳本時仍會暫停解析厦酬。該延遲屬性胆描,另一方面,直到頁面完全解析延遲腳本執(zhí)行

跨域資源共享

CORS允許您定義可以訪問服務(wù)器內(nèi)容的人員和方式仗阅。

但是有一個問題昌讲。使用除GET,HEAD和POST之外的任何方法的請求將啟動預(yù)檢檢查减噪,以確認服務(wù)器已準備好進行跨域請求剧蚣。

為了運行檢查,客戶端發(fā)送另一個請求旋廷,該請求描述了跨域AJAX調(diào)用的來源鸠按,方法和標頭。根據(jù)此信息饶碘,服務(wù)器決定是否處理該呼叫目尖。客戶端收到響應(yīng)后扎运,將啟動對第三方資源的請求瑟曲。

preflight檢查增加了第二次往返,因此可以有效地將您的延遲加倍豪治。


preflight checks

您可以使用以下方法之一來處理預(yù)檢請求:

1.編寫API并僅使用HEAD洞拨,GET,POST负拟,Accept烦衣,Accept-Language,Content-Language和Content-Type來提供內(nèi)容掩浙,因為它們不會啟動預(yù)檢請求花吟。

在接受頭使您能夠定義可接受的內(nèi)容類型的能力。默認情況下厨姚,首選類型為text / html衅澈,但是您可以將application / json或任何其他類型的內(nèi)容作為唯一的可接受類型。然后谬墙,您的后端將檢查Accept標頭今布,然后選擇發(fā)送HTML经备,JSON或其他響應(yīng)。

2.緩存預(yù)檢響應(yīng)以減少后續(xù)檢查部默。

在這種情況下弄喘,您不能依靠通常的Cache-Control標頭來定義緩存策略。但是您可以改用新的Access-Control-Max-Age標頭甩牺。其數(shù)值定義了緩存響應(yīng)所需的秒數(shù)蘑志。

6.使用內(nèi)容傳送網(wǎng)絡(luò)(CDN)

CDN是遍布全球的服務(wù)器網(wǎng)絡(luò)。您可以使用CDN以更有效的方式傳遞靜態(tài)資源(如圖像)贬派。網(wǎng)絡(luò)中的每個服務(wù)器都包含原始服務(wù)器上托管的內(nèi)容的緩存版本急但。

如果來自墨爾本的用戶請求圖像,則網(wǎng)絡(luò)將不會從位于紐約的原始服務(wù)器獲取圖像搞乏。CDN將使用澳大利亞服務(wù)器(或等待時間最少的備用服務(wù)器)來提供緩存的內(nèi)容波桩。

對單頁應(yīng)用程序使用CDN意味著更快地加載腳本并減少了交互時間。增加安全性是一個不錯的獎勵请敦。


結(jié)論說明

這些是我們加快單頁應(yīng)用程序速度的6種方法镐躲。

這是一個獎勵:測量優(yōu)化侍筛,重復(fù)(但僅在需要時)萤皂。

此建議適用于任何應(yīng)用程序,因為優(yōu)化是一個連續(xù)的過程匣椰。

您對代碼所做的每次更改都會影響頁面加載速度裆熙。因此,請評估您的SPA的行為禽笑,并避免過早的優(yōu)化入录,因為開發(fā)人員會花費大量時間來調(diào)整其應(yīng)用程序中不必要的部分。

參考

How to speed-up your Single-Page Application

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末佳镜,一起剝皮案震驚了整個濱河市僚稿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蟀伸,老刑警劉巖蚀同,帶你破解...
    沈念sama閱讀 212,332評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異望蜡,居然都是意外死亡唤崭,警方通過查閱死者的電腦和手機拷恨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,508評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人迅栅,你說我怎么就攤上這事÷瑁” “怎么了?”我有些...
    開封第一講書人閱讀 157,812評論 0 348
  • 文/不壞的土叔 我叫張陵微姊,是天一觀的道長酸茴。 經(jīng)常有香客問我,道長兢交,這世上最難降的妖魔是什么薪捍? 我笑而不...
    開封第一講書人閱讀 56,607評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮配喳,結(jié)果婚禮上酪穿,老公的妹妹穿的比我還像新娘。我一直安慰自己晴裹,他們只是感情好被济,可當我...
    茶點故事閱讀 65,728評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涧团,像睡著了一般只磷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泌绣,一...
    開封第一講書人閱讀 49,919評論 1 290
  • 那天钮追,我揣著相機與錄音,去河邊找鬼阿迈。 笑死畏陕,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的仿滔。 我是一名探鬼主播惠毁,決...
    沈念sama閱讀 39,071評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼崎页!你這毒婦竟也來了鞠绰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,802評論 0 268
  • 序言:老撾萬榮一對情侶失蹤飒焦,失蹤者是張志新(化名)和其女友劉穎蜈膨,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牺荠,經(jīng)...
    沈念sama閱讀 44,256評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡翁巍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,576評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了休雌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灶壶。...
    茶點故事閱讀 38,712評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖杈曲,靈堂內(nèi)的尸體忽然破棺而出驰凛,到底是詐尸還是另有隱情胸懈,我是刑警寧澤,帶...
    沈念sama閱讀 34,389評論 4 332
  • 正文 年R本政府宣布恰响,位于F島的核電站趣钱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏胚宦。R本人自食惡果不足惜首有,卻給世界環(huán)境...
    茶點故事閱讀 40,032評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望枢劝。 院中可真熱鬧绞灼,春花似錦、人聲如沸呈野。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽被冒。三九已至军掂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昨悼,已是汗流浹背蝗锥。 一陣腳步聲響...
    開封第一講書人閱讀 32,026評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留率触,地道東北人终议。 一個月前我還...
    沈念sama閱讀 46,473評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像葱蝗,于是被迫代替她去往敵國和親穴张。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,606評論 2 350

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

  • 一年前寫了一篇JavaScript八張思維導(dǎo)圖两曼,主要是對前端JavaScript知識點的一個系統(tǒng)的整理和總結(jié)皂甘。本篇...
    dykingdy閱讀 1,772評論 0 0
  • 前后端分離算是最近Web開發(fā)的大趨勢了户辫,目前已經(jīng)有大量的公司使用了前后端分離的開發(fā)方式渐夸。那我們就來大概談?wù)勄昂蠖朔?..
    程點閱讀 37,225評論 13 108
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)渔欢,斷路器墓塌,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 夜鶯2517閱讀 127,717評論 1 9
  • 版本:ios 1.2.1 亮點: 1.app角標可以實時更新天氣溫度或選擇空氣質(zhì)量,建議處女座就不要選了,不然老想...
    我就是沉沉閱讀 6,886評論 1 6