什么是網(wǎng)絡(luò)前端?這是用戶計(jì)算機(jī)上的瀏覽器所做的一切。當(dāng)用戶訪問網(wǎng)站時(shí),讓他們看看他們做了什么:
輸入U(xiǎn)RL-解析域名-請(qǐng)求頁(yè)面-解析頁(yè)面并在頁(yè)面中發(fā)送資源請(qǐng)求-呈現(xiàn)資源-輸出頁(yè)面-用戶操作-重新呈現(xiàn)。
通過以上的路徑,我們可以看到瀏覽器分為請(qǐng)求、傳輸、渲染三個(gè)部分來實(shí)現(xiàn)用戶的訪問,本文從這三個(gè)部分分析了如何提高Web前端的性能。
1、 請(qǐng)求
為了減少請(qǐng)求的傳輸,瀏覽器實(shí)現(xiàn)了自己的緩存機(jī)制。瀏覽器緩存是在瀏覽器中存儲(chǔ)所請(qǐng)求的web資源的副本。當(dāng)再次請(qǐng)求相同的URL時(shí),首先檢查緩存。如果存在本地緩存,瀏覽器緩存機(jī)制將根據(jù)Etag和上次修改的機(jī)制來判斷是使用緩存還是從服務(wù)器傳輸資源文件。
有些瀏覽器請(qǐng)求是并發(fā)的,有些是被阻止的,例如,對(duì)圖像、CSS和接口的請(qǐng)求是并發(fā)的;JS文件是被阻止的。當(dāng)請(qǐng)求JS時(shí),瀏覽器會(huì)中斷渲染過程,等待JS文件加載和解析,然后再次渲染。所以把JS文件放在頁(yè)面的末尾。
JS也可以通過兩種方式從阻塞變?yōu)椴⑿校阂环N是創(chuàng)建腳本標(biāo)記并將其插入DOM;另一種是向腳本標(biāo)記添加async屬性。
每個(gè)瀏覽器對(duì)并發(fā)域名的數(shù)量都有限制。IE6/7是2,IE9是10,其他常見的瀏覽器是6。因此,減少資源請(qǐng)求數(shù)量,使用多個(gè)域名配置資源文件,可以大大提高網(wǎng)站性能。
有幾種方法可以減少資源請(qǐng)求的數(shù)量
1通過打包工具,合并資源,減少資源數(shù)量。開發(fā)版本是大量的資源文件。在部署期間,根據(jù)要輸出的類合并多個(gè)文件。同時(shí)實(shí)現(xiàn)了統(tǒng)一輸出。
2在CSS中,csssprite用于減少圖像請(qǐng)求的數(shù)量。
3通過延遲加載技術(shù),在沒有用戶感知的情況下請(qǐng)求資源。
4通過服務(wù)器配置,實(shí)現(xiàn)一個(gè)請(qǐng)求,并返回多個(gè)資源文件,如淘寶CDN。
除了減少請(qǐng)求數(shù)量外,CDN鏡像還可以用來減少網(wǎng)絡(luò)節(jié)點(diǎn),實(shí)現(xiàn)快速響應(yīng)。對(duì)于使用CDN的請(qǐng)求,將根據(jù)用戶的地理位置找到近的CDN節(jié)點(diǎn)。如果請(qǐng)求是新的,它將從資源服務(wù)器復(fù)制到節(jié)點(diǎn),然后返回到客戶端。如果請(qǐng)求已經(jīng)存在,它將直接從節(jié)點(diǎn)返回到客戶端。
通過上面我們知道的緩存機(jī)制,如果我們?cè)诰€部署緩存,我們需要刷新緩存。普通緩存可以通過強(qiáng)刷改變,而CDN緩存則需要通過改變URL來實(shí)現(xiàn)。同時(shí),我們不能要求用戶按Ctrl鍵刷新,所以有效的方法是在部署時(shí)通過打包工具統(tǒng)一更改URL。但是,不建議更改不經(jīng)常更改的庫(kù)文件,例如echart和jQuery。
2、 變速器
從服務(wù)器到客戶端,可以啟用gzip壓縮來提高傳輸效率。
Gzip有10個(gè)級(jí)別,從1到10。壓縮越高,壓縮越小,但是用于壓縮的服務(wù)器硬件資源越多。根據(jù)實(shí)踐,當(dāng)電平為5時(shí),壓縮效果為100k,可壓縮為20K。
3、 渲染
加載HTML后,瀏覽器在解析時(shí)根據(jù)解析結(jié)果進(jìn)行資源請(qǐng)求,生成DOM樹。CSS加載后,渲染引擎根據(jù)生成的DOM樹生成渲染樹。解析所有資源并計(jì)算布局后,將其繪制到瀏覽器界面。當(dāng)用戶操作時(shí),JS修改DOM節(jié)點(diǎn)或樣式,重新繪制并重新排列它們。重繪是指繪制與DOM節(jié)點(diǎn)相對(duì)應(yīng)的渲染節(jié)點(diǎn),重排是指重新計(jì)算這些節(jié)點(diǎn)在瀏覽器界面中的位置。顯然,重新排列是非常注重性能的。我們要做的是減少重組的次數(shù)。
在構(gòu)建DOM樹時(shí),我們可以通過減少DOM節(jié)點(diǎn)來優(yōu)化性能。起初,他們使用表布局,節(jié)點(diǎn)的深度和數(shù)量都比較復(fù)雜,而且性能很差。同樣,作為級(jí)聯(lián)樣式表,CSS不應(yīng)該太深,否則遍歷成本非常高。此外,CSS的expression屬性會(huì)消耗大量的性能。如果不能使用,就不能使用。如果動(dòng)畫效果可以用CSS編寫,就不需要JS了。如果渲染引擎不同,性能損失也不同。
以上是解析和呈現(xiàn)的過程。讓我們來談?wù)動(dòng)脩艚换サ倪^程。用戶操作將導(dǎo)致重畫和重排,這肯定會(huì)導(dǎo)致重畫,而重畫可能不會(huì)。它究竟是如何引起重組的?簡(jiǎn)單的定義、DOM結(jié)構(gòu)的更改和DOM樣式的幾何結(jié)構(gòu)的更改都會(huì)導(dǎo)致重新排列。幾何屬性,顧名思義,是長(zhǎng)方體模型的屬性,如寬度、高度、邊界、外部面片和內(nèi)部面片。還有邊距屬性,例如偏移量。
重新調(diào)度是消耗能量的方法。減少重排的方法如下:
1如果需要多次更改DOM,請(qǐng)先在內(nèi)存中更改它,一次將其插入DOM。
2如果多次更改樣式,請(qǐng)合成一個(gè)樣式并將其插入dom中。
3由于位置值固定的,因此它與文檔流分離。操作這樣的DOM節(jié)點(diǎn)不會(huì)導(dǎo)致頁(yè)面重新排列。所以animation元素設(shè)置位置以將其從文檔流中取出。
4當(dāng)DOM節(jié)點(diǎn)的顯示等于none時(shí),它將不存在于渲染樹中。因此,如果有復(fù)雜的操作,首先使其顯示為“無”,然后在所有操作完成后將顯示設(shè)置為“塊”。這樣,它只會(huì)被重新安排兩次。
5當(dāng)您獲得導(dǎo)致重新排序的屬性值時(shí),它將存儲(chǔ)在變量中,并且在再次使用時(shí)不會(huì)再次重新排列。獲取這些屬性會(huì)導(dǎo)致重新排列:offsettop、offsetleft、offsetwidth、offsetHeight、scrolltop、scrollleft、scrollwidth、scrollheight、ClientTOP、clientleft、clientwidth、clientheight、clientheight
以上是瀏覽器如何將資源轉(zhuǎn)換為可見頁(yè)面。除了根據(jù)瀏覽器流程總結(jié)出的性能優(yōu)化外,我們還需要將JavaScript作為一個(gè)程序來進(jìn)行優(yōu)化。讓我們看看JavaScript的垃圾收集機(jī)制。
JavaScript引擎將注銷不再使用的本地變量,并以固定的時(shí)間間隔釋放它們占用的內(nèi)存。閉包的存在會(huì)使引用一直存在并且不能被釋放。直到瀏覽器卸載頁(yè)面,全局變量的生命周期才會(huì)結(jié)束。因此,一般來說,內(nèi)存溢出是由全局變量的不釋放和關(guān)閉引起的。為了防止內(nèi)存溢出,我們可以執(zhí)行以下操作:
1業(yè)務(wù)代碼放在匿名立即執(zhí)行函數(shù)中,并將在執(zhí)行后立即釋放。
2使用較少的全局變量,并手動(dòng)注銷使用的變量。
3當(dāng)關(guān)閉不可避免時(shí),請(qǐng)注意細(xì)節(jié)。不用的時(shí)候就把它注銷。
4通過瀏覽器自己的工具配置文件檢查內(nèi)存活動(dòng)。如果是波浪形的,表示正常。如果是斜向遞增,則表示有內(nèi)存不會(huì)釋放,需要檢查相應(yīng)的功能。
但并非不重要的是,異步檢索的值在函數(shù)中返回
毫無疑問,由于函數(shù)內(nèi)的返回是異步的,返回只能是未定義的,而不是所需的數(shù)據(jù)。因此,為了返回?cái)?shù)據(jù),AJAX的async屬性設(shè)置為false,并將async屬性從asynchronous更改為synchronous以獲取數(shù)據(jù)。但是,問題是同步會(huì)中斷呈現(xiàn)過程,也就是說,當(dāng)請(qǐng)求等待返回時(shí),整個(gè)頁(yè)面被卡住,用戶的操作不會(huì)響應(yīng)。這個(gè)問題的真正解決方案是返回promise對(duì)象,而不是將異步更改為同步。