解析域名 -> 請求頁面 -> 解析頁面并發(fā)?..."/>
溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何提升Web前端性能?

發(fā)布時(shí)間:2020-07-04 14:56:11 來源:網(wǎng)絡(luò) 閱讀:180 作者:mdadmmeng 欄目:系統(tǒng)運(yùn)維
什么是WEB前端呢?就是用戶電腦的瀏覽器所做的一切事情。我們來看看用戶訪問網(wǎng)站,瀏覽器都做了哪些事情:輸入網(wǎng)址 –> 解析域名 -> 請求頁面 -> 解析頁面并發(fā)送頁面中的資源請求 -> 渲染資源 -> 輸出頁面 -> 監(jiān)聽用戶操作 -> 重新渲染。

通過上面的路徑可以看出瀏覽器分為請求、傳輸、渲染三部分來實(shí)現(xiàn)用戶的訪問,本文就從這三個(gè)部分來淺析如何提升WEB前端性能。

請求

瀏覽器為了減少請求傳輸,實(shí)現(xiàn)了自己的緩存機(jī)制。瀏覽器緩存就是把一個(gè)已經(jīng)請求過的Web資源拷貝一份副本存儲(chǔ)在瀏覽器中,當(dāng)再次請求相同的URL時(shí),先去查看緩存,如果有本地緩存,瀏覽器緩存機(jī)制會(huì)根據(jù)驗(yàn)證機(jī)制(Etag)和過期機(jī)制(Last-Modified)進(jìn)行判斷是使用緩存,還是從服務(wù)器傳輸資源文件。具體流程如下圖所示:

如何提升Web前端性能?

如何從請求、傳輸、渲染3個(gè)方面提升Web前端性能

瀏覽器的請求有些是并發(fā)的,有些是阻塞的,比如:圖片、CSS、接口的請求是并發(fā);JS文件是阻塞的。請求JS的時(shí)候,瀏覽器會(huì)中斷渲染進(jìn)程,等待JS文件加載解析完畢,再重新渲染。所以要把JS文件放在頁面的最后。

JS也可以通過兩種方式由阻塞改成并行:一種是通過創(chuàng)建script標(biāo)簽,插入DOM中;另一種是在Script標(biāo)簽中增加async屬性。

每種瀏覽器對同一域名并發(fā)的數(shù)量有限制,IE6/7是2,IE9是10,其他常見的瀏覽器是6,所以減少資源請求數(shù)量和使用多域名配置資源文件,能大大提高網(wǎng)站性能。

減少資源請求數(shù)量的方法,大致有以下幾種:

1、通過打包工具,合并資源,減少資源數(shù)量。就是開發(fā)版本是很多個(gè)資源文件,部署的時(shí)候,按類合并成幾個(gè)文件來輸出。在實(shí)現(xiàn)模塊管理的同時(shí),實(shí)現(xiàn)統(tǒng)一輸出。

2、CSS中,使用css sprite減少圖片請求數(shù)量。

3、通過延遲加載技術(shù),在用戶無感知的情況下請求資源。

4、通過服務(wù)器配置,實(shí)現(xiàn)一次請求,返回多個(gè)資源文件,如淘寶CDN那樣。

除了減少請求數(shù)量,也可以使用CDN鏡像,來減少網(wǎng)絡(luò)節(jié)點(diǎn),實(shí)現(xiàn)快速響應(yīng)。使用了CDN的請求,會(huì)根據(jù)用戶所處的地理位置,找尋最近的CDN節(jié)點(diǎn),如果請求是新的,則從資源服務(wù)器拷貝到節(jié)點(diǎn),然后再返回給客戶端。如果請求已經(jīng)存在,則直接從節(jié)點(diǎn)返回客戶端。

通過上面我們了解的緩存機(jī)制,如果我們部署上線的時(shí)候,是需要刷新緩存的。普通緩存通過強(qiáng)刷就能改過來,而CDN緩存則需要通過改變URL來實(shí)現(xiàn)。同時(shí)我們不可能要求用戶按著Ctrl來刷新,所以通過打包工具,在部署的時(shí)候,統(tǒng)一更改URL是最有效的方式。而不常變更的庫文件,比如echart、jquery,則不建議更改。

傳輸

從服務(wù)器往客戶端傳輸,可以開啟gzip壓縮來提高傳輸效率。

Gzip有從1-10的十個(gè)等級。越高壓縮的越小,但壓縮使用的服務(wù)器硬件資源就越多。根據(jù)實(shí)踐,等級為5的時(shí)候最均衡,此時(shí)壓縮效果是100k可以壓縮成20k。

https://www.51cto.com/it/news/2019/1217/17548.html

渲染

瀏覽器在加載了html后,就會(huì)一邊解析,一邊根據(jù)解析出來的結(jié)果進(jìn)行資源請求,并生成DOM樹。而加載完畢的CSS,則被渲染引擎根據(jù)生成好的DOM樹,來生成渲染樹。等所有資源解析完畢計(jì)算好layout后,向?yàn)g覽器界面繪制。隨著用戶操作,JS會(huì)修改DOM節(jié)點(diǎn)或樣式,重新繪制和重新排列。重新繪制指的是繪制DOM節(jié)點(diǎn)對應(yīng)的渲染節(jié)點(diǎn),重新排列是指重新計(jì)算這些節(jié)點(diǎn)在瀏覽器界面的位置。很顯然,重排是非常耗性能的。我們要做的是減少重排的次數(shù)。

生成DOM樹的時(shí)候,我們可以通過減少DOM節(jié)點(diǎn)來優(yōu)化性能。最初都是用table布局,節(jié)點(diǎn)深度和數(shù)量相當(dāng)復(fù)雜,性能很差。同樣CSS作為層疊樣式表,層級也不可太深,不然遍歷的成本很高。另外CSS的expression屬性相當(dāng)耗性能,能不用則不用。動(dòng)畫效果能用CSS寫的就不用JS寫,渲染引擎不一樣,性能損耗也不一樣。

上面說的是解析渲染的過程,我們再接著說說用戶交互操作的過程。用戶操作就會(huì)導(dǎo)致重繪和重排,重排一定會(huì)引起重繪,而重繪不一定會(huì)引起重排。到底怎樣會(huì)引起重排呢?簡單的定義,DOM結(jié)構(gòu)的變化,以及DOM樣式中幾何屬性的變化,就會(huì)導(dǎo)致重排。幾何屬性顧名思義,就是寬、高、邊框、外補(bǔ)丁、內(nèi)補(bǔ)丁等俗稱盒模型的屬性。同時(shí)還有offset之類的邊距屬性。

重排是最耗能的,減少重排的方法有:

1、如果需要多次改變DOM,則先在內(nèi)存中改變,最后一次性的插入到DOM中。

2、同上一條,如果多次改變樣式,合成一條,再插入DOM中。

3、由于position的值為absoute和fixed時(shí)候,是脫離文檔流的,操作此類DOM節(jié)點(diǎn),不會(huì)引起整頁重排。所以動(dòng)畫元素設(shè)置position使其脫離文檔流。

4、當(dāng)DOM節(jié)點(diǎn)的display等于none的時(shí)候,是不會(huì)存在于渲染樹的,所以如果有比較復(fù)雜的操作,先使其display等于none,等待所有操作完畢后,再將display設(shè)成block,這樣就只重排兩次。

5、獲取會(huì)導(dǎo)致重排的屬性值時(shí),存入變量,再次使用時(shí)就不會(huì)再次重排。獲取這些屬性會(huì)導(dǎo)致重排:offsetTop、offsetLeft、offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

以上就是瀏覽器如何把資源變成肉眼所見的頁面的,除了上述根據(jù)瀏覽器流程而總結(jié)出來的性能優(yōu)化,我們還需要看看javascript作為程序,需要的優(yōu)化。先來看看javascript的垃圾回收機(jī)制。

Javascript的引擎會(huì)在固定的時(shí)間間隔,將不再使用的局部變量注銷掉,釋放其所占的內(nèi)存。而閉包的存在,將使引用一直存在,無法被釋放掉。全局變量的生命周期直至瀏覽器卸載頁面才會(huì)結(jié)束。所以一般來講,內(nèi)存溢出就是由于全局變量的不釋放和閉包引起。為了防止內(nèi)存溢出,我們可以做的方法有:

1、業(yè)務(wù)代碼放在匿名立即執(zhí)行函數(shù)里面,執(zhí)行完畢會(huì)立即釋放掉。

2、少用全局變量,同時(shí)用完的變量手動(dòng)注銷掉。

3、使用回調(diào)來代替閉包訪問內(nèi)部屬性

4、當(dāng)不可避免使用閉包時(shí),慎重的對待其中的細(xì)節(jié)。不用的時(shí)候注銷掉。

5、通過瀏覽器自帶的工具profiles,來檢查內(nèi)存活動(dòng)情況。如果是波浪型的,說明正常。如果是傾斜式漸進(jìn)上漲的,說明有內(nèi)存不會(huì)被釋放,需要檢查相應(yīng)的函數(shù)。

最后再說一點(diǎn),函數(shù)里返回異步取的值,經(jīng)常有人這么:

?Var?getList?=?function(){?$.ajax().then(function(data){

???Return?data;

})?};

Var?users?=?getList();

毫無疑問,由于函數(shù)內(nèi)的返回是異步的,所以返回只能是undefined,而不是想要的data。于是為了實(shí)現(xiàn)返回data,就把a(bǔ)jax的async屬性設(shè)置成了false,由異步改為同步,來獲取到data。然而最大的問題來了,同步是會(huì)中斷渲染進(jìn)程的,也就是請求返回的等待中,整個(gè)頁面是卡死的,用戶操作也不會(huì)有響應(yīng)。這個(gè)問題真正的解決方案是返回promise對象,而不是把異步改成同步。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI