你不知道的 Web 性能優(yōu)化 | 原力計劃-重拳出擊

你遇到過打開一個網(wǎng)站需要10秒以上的嗎?這種網(wǎng)頁響應(yīng)非常緩慢,占用大量的CPU和內(nèi)存,瀏覽起來常常有卡頓,頁面的動畫效果也不流暢。你會有什么反應(yīng)?我猜想,大多數(shù)用戶會關(guān)閉這個頁面,改為訪問其他網(wǎng)站。作為一個開發(fā)者,肯定不愿意看到這種情況,那么怎樣才能提高性能呢?

有興趣的同學(xué)可以去我的GitHub,里面有我的分享的學(xué)習(xí)過程和blog:github.com/193Eric。

使用Web Worker

Web Worker 是HTML5 提供的一個Javascript多線程解決方案,運行在瀏覽器后臺。如我們所知js是個單線程的,js引擎在運行js的時候,不能干其他事。不過在使用中需要注意以下幾點:

它是一種JavaScript 工作線程,不能直接訪問DOM

能發(fā)送網(wǎng)絡(luò)請求。

它在不用時會被中止,并在下次有需要時重啟

在開發(fā)過程中,可以通過 localhost 使用服務(wù)工作線程,但如果要在網(wǎng)站上部署服務(wù)工作線程,需要在服務(wù)器上設(shè)置 HTTPS。

Worker 線程無法讀取本地文件,即不能打開本機(jī)的文件系統(tǒng)(file://),它所加載的腳本,必須來自網(wǎng)絡(luò),這樣做主要是為了安全,因為是可以通訊的,如果被別人修改了文件,引入了本地的js,進(jìn)行通訊就會出現(xiàn)問題,所以只能訪問同源的網(wǎng)絡(luò)文件。(重點,所以本地調(diào)試的時候需要開啟服務(wù),用node或者后臺語言啟動

web Worker 與主線程的交互速度

我們用代碼來看下從主線程 --> web worker --> 主線程 最簡單的需要多長時間。

webWorker

var?worker?=?new?Worker("worker.js");

console.log(new?Date().getTime())?//?開始時間

worker.postMessage("123456")

worker.onmessage?=?function?(e)?{

console.log(new?Date().getTime())?//?接收時間

}

</script>

</body>

<html>


//webWorker.js

onmessage=function(evt){

vard=evt.data//通過evt.data獲得發(fā)送來的數(shù)據(jù)

postMessage(d)//將獲取到的數(shù)據(jù)發(fā)送會主線程

}

經(jīng)過幾次測試,大概的事件在30-50ms之間(當(dāng)然這個值會隨著機(jī)器性能問題有大有?。?,正常的傳輸速度是很快的。

web Worker 優(yōu)化策略與實踐

案例:大量的js計算(fibonacci數(shù)列計算)

varworker=newWorker("worker.js");

letbeginTime=newDate().getTime()

console.log(beginTime)

letfibonacci=(n)=>{

returnn<2?n:fibonacci(n-1)+fibonacci(n-2);

};

fibonacci(45)

letendTime=newDate().getTime()

console.log(`${endTime}---------歷時${(endTime-beginTime)/1000}s`)

我們在主線程計算fibonacci(45)看看需要多少時間,在計算的時候頁面是卡主的,會非常影響用戶體驗。

然后我們看看放在web worker里面是什么情況。

//index.htmlvarworker=newWorker("worker.js");letbeginTime=newDate().getTime()console.log(beginTime)worker.postMessage("fibonacci");worker.onmessage=function(e){letendTime=newDate().getTime()console.log(e,`${endTime}---------歷時${(endTime-beginTime)/1000}s`)};console.log("working")console.log("working")console.log("working")

//worker.jsonmessage=function(evt){vard=evt.data;//通過evt.data獲得發(fā)送來的數(shù)據(jù)letfibonacci=(n)=>{returnn<2?n:fibonacci(n-1)+fibonacci(n-2);};letdata=fibonacci(45)postMessage(data);//將獲取到的數(shù)據(jù)發(fā)送會主線程}

可以看到,計算的時間是差不多的,但是并沒有阻礙頁面的運行。所以,一些高計算耗費時間的功能,可以放到web worker中計算完成后再返回回來。

SPA項目首頁白屏問題

現(xiàn)在三大框架(vue,react,angular)的興起,越來越多的項目采用SPA這種接近原生app體驗的架構(gòu)方式。采用SPA模式,就意味著,首頁或者main.js過大,首屏加載的速度會受到很大的限制。會存在一定時間的白屏。

SPA項目因為html都是js去生成的(虛擬Dom原理),所以在js沒有執(zhí)行加載完之前,dom是不會有的。一開始客戶端從服務(wù)端獲取到html只是一個空殼,所以會顯示白屏。

下面列出一些解決方案:

1.服務(wù)端渲染SSR(加快首屏加載和SEO)

SSR是一個可以有效的提高首屏渲染速度的方法,之后我會開單張去單獨實踐服務(wù)端渲染。

2.預(yù)渲染

預(yù)渲染是一個方案,使用爬蟲技術(shù)。由于我們打包過后的都是一些js文件,使用一些技術(shù)(puppeteer)可以爬取到項目在chrome瀏覽器展示的頁面,然后把它寫入js,和打包文件一起。類似prerender-spa-plugin

不過這種技術(shù)的缺點也很明顯,我們在打包過程中,所展示的頁面是當(dāng)時環(huán)境下的數(shù)據(jù),也就是說如果首頁有很多的動態(tài)獲取的數(shù)據(jù)(比如說實時的股票價格),那如果采用這種方案,用戶第一眼看到并不是當(dāng)時數(shù)據(jù),會認(rèn)為是個錯誤信息。

3.骨架屏(占位塊和圖片)

骨架屏可以說現(xiàn)在比較實用的首屏優(yōu)化技術(shù)了,方便也不是很復(fù)雜。骨架屏類似于app的啟動頁,一般我們進(jìn)入app都會有宣傳的啟動頁,然后才看到首頁。骨架屏就是這樣,用戶進(jìn)來首先看到的是骨架屏,然后首頁渲染完之后,再把骨架屏干掉。

骨架屏主要有兩種方式可以完成:

通過編譯的時候自動生成還是puppeteer(上面說了預(yù)渲染也用,它主要是能在代碼里面喚起chrome瀏覽器,或者后臺喚起,也就是沒有彈出瀏覽器,但是可以獲取到真實瀏覽器中渲染的內(nèi)容),有了它我們就能獲取到瀏覽器里面的dom元素,然后通過對頁面中元素進(jìn)行刪減或增添,對已有元素進(jìn)行修改生成我們想要的骨架,然后將修改后的 HTML 和 CSS 樣式提取出來,這樣就是骨架屏了。當(dāng)然遇到了圖片的話,還是需要轉(zhuǎn)成svg的形式,或者base64這樣就不需要網(wǎng)絡(luò)請求了。

通過設(shè)計圖+布局這是一種直接重新寫一個頁面的方式,圖片的話采用svg和base64的形式,生成一個dom,解析注入到服務(wù)器返回的index.html里面(ssr render注入)。

現(xiàn)在網(wǎng)絡(luò)上的項目,最能提現(xiàn)的就是餓了么的h5了,我們可以通過手機(jī)瀏覽器打開餓了么。

我們首先看到是骨架屏,然后過一會才會看到首屏,這就是餓了么用了這種技術(shù),很大的提高了用戶的體驗。page-skeleton-webpack-plugin項目地址:https://github.com/ElemeFE/page-skeleton-webpack-plugin

SSL延遲有多大?

我們知道http是經(jīng)過TCP三次握手就可以成功通訊 。再來看Https鏈接,它也采用TCP協(xié)議發(fā)送數(shù)據(jù),所以它也需要上面的這三步握手過程。而且,在這三步結(jié)束以后,它還有一個SSL握手。

HTTP耗時 = TCP握手 ; HTTPS耗時 = TCP握手 + SSL握手

在研究ssl延遲之前,我們先來學(xué)一個命令行工具curl,-w,–write-out參數(shù)。顧名思義,write-out的作用就是輸出點什么。curl的-w參數(shù)用于在一次完整且成功的操作后輸出指定格式的內(nèi)容到標(biāo)準(zhǔn)輸出。

主要了解下幾個參數(shù):

http_code http狀態(tài)碼

time_total 總時間,按秒計。

time_namelookup DNS解析時間,從請求開始到DNS解析完畢所用時間

time_connect 連接時間,從開始到建立TCP連接完成所用時間,

time_appconnect 連接建立完成時間,如SSL/SSH等建立連接或者完成三次握手時間。

我們主要用time_connect(TCP握手的耗時),time_appconnect(SSL握手的耗時)

終端輸入curl -w "TCP握手的耗時: %{time_connect}, SSL握手的耗時: %{time_appconnect}\n" -so /dev/null https://www.taobao.com

我們可以看到ssl耗時是tcp的三倍左右,具體數(shù)字取決于CPU的快慢和網(wǎng)絡(luò)狀況。

所以,如果是對安全性要求不高的場合,為了提高網(wǎng)頁性能,建議不要采用保密強(qiáng)度很高的數(shù)字證書。

防抖節(jié)流那些事

在開發(fā)過程中我們很多時候會碰到需要防抖和節(jié)流去解決問題。不要小看它們,沒有它們的話,特定情況下的會造成很大的性能阻塞。

防抖(當(dāng)持續(xù)觸發(fā)事件時,一定時間段內(nèi)沒有再觸發(fā)事件,事件處理函數(shù)才會執(zhí)行一次)防抖我們可以理解為,存在一個scroll事件,只要滾動就會觸發(fā)handler回調(diào)函數(shù),防抖的處理是,等scroll事件完全停下來1000ms(這個值自行設(shè)定)之后,再出觸發(fā)handler函數(shù)。

節(jié)流(當(dāng)持續(xù)觸發(fā)事件時,保證一定時間段內(nèi)只調(diào)用一次事件處理函數(shù))節(jié)流顧名思義,觸發(fā)scroll事件的時候,并不立即執(zhí)行handle函數(shù),每隔1000ms(這個值自行設(shè)定)才會執(zhí)行一次handle函數(shù)

區(qū)別:節(jié)流是每一個時間段之后就會觸發(fā)一次,存在間隙的連續(xù)觸發(fā),而防抖不一樣,只會在最后才觸發(fā)一次。

重排與重繪的相愛相殺

從前面的文章(瀏覽器渲染過程剖析)已經(jīng)學(xué)到了網(wǎng)頁的生成過程。

HTML代碼轉(zhuǎn)化成DOM

CSS代碼轉(zhuǎn)化成CSSOM(CSS Object Model)

結(jié)合DOM和CSSOM,生成一棵渲染樹(包含每個節(jié)點的視覺信息)

生成布局(layout),即將所有渲染樹的所有節(jié)點進(jìn)行平面合成

將布局繪制(paint)在屏幕上

1-3步都很快,耗時的是第四步和第五步。這兩步合稱”渲染“,在網(wǎng)上生成的過程中,網(wǎng)頁至少會渲染一次。

有三種情況會導(dǎo)致瀏覽器重新渲染:

1.修改DOM

2.修改樣式表

3.用戶事件(比如鼠標(biāo)懸停、頁面滾動、輸入框鍵入文字、改變窗口大小等等)

重新渲染,就需要重新生成布局和重新繪制。前者叫做"重排"(reflow),后者叫做"重繪"(repaint)。

重排和重繪不斷的觸發(fā),是影響網(wǎng)頁性能低下的根本原因。提高網(wǎng)頁性能,就是要降低"重排"和"重繪"的頻率和成本,盡量少觸發(fā)重新渲染。重排必定會重繪,而重繪不一定重排。

最后

喜歡小編的可以點個贊關(guān)注小編哦,小編每天都會給大家分享文章。

我自己是一名從事了多年的前端老程序員,小編為大家準(zhǔn)備了新出的前端編程學(xué)習(xí)資料,免費分享給大家!

如果你也想學(xué)習(xí)前端,加入此Q群:950919261

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 你害怕與人交際嗎?你是那個碰見人就會躲的人嗎?在與人交流的過程中,你是否常常會尷尬到不知道說什么。 其實,沒有人喜...
    譯耳閱讀 1,664評論 1 29
  • 喜歡最近的八點鐘 夕陽西下
    zxy我在等你閱讀 168評論 0 0
  • 一個普通人,怎么做對社會有價值。小文的話讓我一下子清晰了。 做好自己,用自己的身體力行,影響身邊的人。取得一定的成...
    56東南西閱讀 274評論 0 0

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