引言: 轉前端一年了,期間工做較忙,也沒時間整理一些知識體系,此係列文章是對前端基礎的一些回顧與總結。本文主要介紹瀏覽器工做的原理以及一些優化手段。
以chorme爲例:php
須要注意的是,NPAPI是指瀏覽器對系統或外部的一些程序的調用接口,好比播放視頻的 flash 插件,而Pepper實際上是基於NPAPI改進的插件架構。css
主流的瀏覽器內核主要有2種,Webkit 和 Geoko ,雖然 chorme 如今的內核更換爲 blink ,但其實 blink是基於webkit的,差別不大。其渲染過程分別以下:html
這兩個內核的渲染流程大同小異,主要的過程能夠總結爲下列5個:前端
使用chorme瀏覽器的開發者工具,咱們很容易看到這5個過程的時間線,下面是segmentfault主頁的渲染截圖:vue
能夠看到上述流程的耗時,甚至能夠統計到每一幀的耗時分佈,從而對影響渲染性能的代碼精肯定位。其中黃色爲JS,紫色爲Style和Layout,綠色爲Paint和Composite部分,選中每一個部分會顯示各自的花費時間等信息,能夠看出這個圖片中JS運行的時間太長。目前的顯示設備通常刷新率是60FPS,因此理想中每幀的時間最好爲16毫秒。html5
須要注意的一點是,這裏的步驟執行並無特定的順序,爲保證渲染的速度,瀏覽器一開始接收到html時就開始執行解析的過程,而且遇到須要重繪和重排的時候會重複執行這些步驟,下面咱們詳細介紹一下這5個過程。node
瀏覽器在接收到html文件後即開始解析和構建DOM樹,在碰到js代碼段時,因爲js代碼可能會改變dom的結構,因此爲避免重複操做,瀏覽器會中止dom樹構建,先加載並解析js代碼。而對於css,圖片,視頻等資源,則交由資源加載器去加載,這個過程是異步的,並不會阻礙dom樹的生成。這個過程須要注意的點是:react
display:none
的元素、註釋存在於dom樹中async
或 defer
瀏覽器在碰到<link>
和 <style>
標籤時,會解析css生成cssom , 固然,link標籤須要先將css文件加載完成才能解析。
須要注意的是:webpack
在cssom 和dom 樹都構建完成後,瀏覽器會將他們結合,生成渲染對象樹,渲染樹的每個節點,包含了可見的dom節點和節點的樣式 。
須要注意的是:git
display:none
是不會放入渲染樹的。visibility: hidden
的元素在Render Tree中這一步是瀏覽器遍歷渲染對象樹,並根據設備屏幕的信息,計算出節點的佈局、位置,構建出渲染布局樹(render layout)。渲染布局樹輸出的就是咱們常說的盒子模型,須要注意的是:
float
, absolute
, fixed
的元素的位置會發生偏移瀏覽器對生成的佈局樹進行繪製,由用戶界面後端層將每一個節點繪製出來。此時,Webkit內核還須要將渲染結果從Renderer進程傳遞到Browser進程。
前面講到,js代碼能夠訪問和修改dom節點和css,因此在解析js的過程當中會致使頁面從新佈局和渲染,這就是重繪(repaint)和迴流(reflow)。
重繪是指css樣式的改變,但元素的大小和尺寸不變,而致使節點的從新繪製。
任何對元素樣式,如background-color
、border-color
、visibility
等屬性的改變。css 和 js 均可能引發重繪。
迴流(reflow)是指元素的大小、位置發生了改變,而致使了佈局的變化,從而致使了佈局樹的從新構建和渲染。
固然,咱們的瀏覽器不會每一次reflow都馬上執行,而是會積攢一批,這個過程也被成爲異步reflow,或者增量異步reflow。可是有些狀況瀏覽器是不會這麼作的,好比:resize窗口,改變了頁面默認的字體,等。對於這些操做,瀏覽器會立刻進行reflow。
優化並非無目的的,而是經過分析頁面各個維度,找到亟待優化的方向或者具體到某段代碼。下面就討論一下如何對頁面作性能分析和測速監控。
chorme得devtools相信全部的前端開發者都用過,它不只提供了平常開發中極強的調試能力,同時也具有着極強的頁面分析能力。
通常來講,咱們打開一個頁面,指望的是頁面的響應和呈現速度和流暢的交互體驗。因此,頁面的測速指標能夠大體歸納爲: 白屏時間,首屏時間,可交互時間。
window.performance是w3c提供的用來測量網頁和Web應用程序的性能api。其中performance timing提供了延時相關的性能信息,能夠高精度測量網站性能。timing的總體結構以下圖所示:
關於性能優化,涉及的方向太廣了,從網絡請求到數據庫,整條鏈路都有其可優化的地方。這裏我只總結一下前端比較須要關注的一些優化點。這裏從兩個個維度進行討論:
從上文可知,瀏覽器渲染網頁的前提是下載相關的資源,html文檔、css文檔、圖片資源等。這些資源是客戶端基於HTTP協議,經過網絡請求從服務器端請求下載的,你們都知道,有網絡,一定有延遲,而資源加載的網絡延遲,是頁面緩慢的一個重要因素。因此,如何使資源更快、更合理的加載,是性能優化的必修課。
因爲HTTP的限制,在創建一個tcp請求時須要一些耗時,因此,咱們對資源進行合併、壓縮,其目的是減小http請求數和減少包體積,加快傳輸速度。
segmentfault.com 的雪碧圖圖標
將一些靜態資源文件託管在第三方CDN服務中,一方面能夠減小服務器的壓力,另外一方面,CDN的優點在於,CDN系統可以實時地根據網絡流量和各節點的鏈接、負載情況以及到用戶的距離和響應時間等綜合信息將用戶的請求從新導向離用戶最近的服務節點上,保證資源的加載速度和穩定性。
緩存的範圍很廣,好比協議層的DNS解析緩存、代理服務器緩存,到客戶端的瀏覽器本地緩存,再到服務端的緩存。一個網絡鏈路的每一個環節都有被緩存的空間。緩存的目的是簡化資源的請求路徑,好比某些靜態資源在客戶端已經緩存了,再次請求這個資源,只須要使用本地的緩存,而無需走網絡請求去服務端獲取。
segmentfault 的主頁的一些靜態資源使用了緩存,上面是一些控制緩存的header首部字段
分片指得是將資源分佈到不一樣的主機,這是爲了突破瀏覽器對同一臺主機創建tcp鏈接的數量限制,通常爲6~8個。現代網站的資源數量有50~100個很常見,因此將資源分佈到不一樣的主機上,能夠創建更多的tcp請求,下降請求耗時,從而提高網頁速度。
從segmentfault 的主頁請求能夠看出,網站將靜態js文件和圖片都放在了不一樣的子域名下。
能夠升級咱們的網絡協議,好比使用HTTP2,quic 之類的,代替以前的http1.1,從協議層優化資源的加載。能夠參考我以前的文章。
雖然作好了靜態數據的加載優化,可是仍是會出現一種情景,即靜態數據已經加載完畢,但頁面仍是在轉菊花,頁面尚未進入可交互狀態,這是由於現現在的網站開發模式,先後端分離已經成爲主流,再也不由php或jsp服務端渲染前端頁面,而是前端先加載靜態數據,再經過ajax異步獲取服務器的數據,進而從新渲染頁面。這就致使了異步從接口獲取數據也是網頁的一個性能瓶頸。響應緩慢,不穩定的接口,會致使用戶交互體驗極差,頁面渲染速度也不理想。好比點擊一個提交數據的按鈕,接口速度慢,頁面上菊花須要轉很久才能交換完數據。
爲了提高用戶體驗,咱們認爲首屏的渲染速度是極爲重要的,用戶進來頁面,首頁可見區域的加載能夠由服務端渲染,保證了首屏加載速度,而不可見的部分則能夠異步加載,甚至作到子路由頁面的預加載。業界已經有不少同構直出的方案,好比vue的nuxt , react的beidou等。
前端常常有這樣的場景,完成一個功能須要先請求第一個接口得到數據,而後再根據數據請求第二個接口獲取第二個數據,而後第3、第四...前端一般須要經過promise或者回調,一層一層的then下去,這樣顯然是很消耗性能的
一般後臺接口都按必定的粒度存在的,不可能一個接口知足全部的場景。這是不可避免的,那麼如何作到只發送一個請求就能實現功能呢?有一種不錯的方案是,代理服務器實現請求合併,即後臺的接口只須要保證健壯和分佈式,而由nodejs(固然也可使用其餘語言)建設一層代理中間層,流程以下圖所示:
前端只須要按找約定的規則,向代理服務器發起一次請求,由代理服務器向接口服務器發起三次請求,再將目標數據返回給客戶端。這樣作的好處是:一方面是代理服務器代替前端作了接口合併,減小了前端的請求數量;另外一方面代理服務器能夠脫離HTTP的限制,使用更高效的通訊協議與服務器通訊;
頁面中的css 和 js 會阻塞html的解析,由於他們會影響dom樹和render樹。爲了不阻塞,咱們能夠作這些優化:
defer
和 async
屬性告訴瀏覽器能夠異步加載,不阻塞解析重繪和迴流在實際開發中是很難避免的,咱們能作的就是儘可能減小這種行爲的發生。
fixed
或 absolute
的 position
,那麼修改他們的 CSS 是不會 Reflow 的。display:none
,再修改屬性,這裏只發生一次迴流。transform
來作形變和位移,不會形成迴流這最能體現一個前端工程師的水平了,高性能的代碼能在實現功能的同時,還兼顧性能。下面是一些好的實踐:
debounce
和 throttle
這兩個函數。好比scroll
和touch
事件...
優化沒有正確答案,優化的手段也層出不窮,這裏也沒法歸納全面,只列舉了一些我瞭解過的。其實除了前端,後端也有許多可優化的地方,好比接口緩存啊,數據庫緩存啊等等。這個本騷年就瞭解的不深了。
性能一直是前端開發很重要的一個課題。性能優化也是一條不見盡頭的路,任重而道遠啊~
參考文章:
https://segmentfault.com/a/11...
https://sylvanassun.github.io...
https://www.html5rocks.com/zh...
https://juejin.im/post/5a966b...
https://juejin.im/post/59672f...
https://tech.meituan.com/perf...
https://segmentfault.com/a/11...
https://www.jianshu.com/p/268...