前端面試常考的有關瀏覽器方面的知識

瀏覽器渲染機制/瀏覽器渲染過程

1. 建立/更新DOM樹和請求css/image/js: 瀏覽器請求HTML代碼後 在生成DOM樹最開始的階段(字節 -> 字符) 並行發起css/image/js請求css

2. 建立/更新 CSSOM樹: CSS文件下載 開始構建CSSOM樹

3. 建立/更新 渲染樹: 全部CSS文件下載完成後 CSSOM樹構建結束和DOM樹一塊兒生成渲染樹html

4. 佈局: 經過渲染樹 瀏覽器已經知道網頁有哪些節點 各個節點CSS定義以及它們的從屬關係 計算出每一個節點在屏幕中的位置

5. 繪畫: 根據佈局 按照算出來的規則 經過顯卡 把內容畫到屏幕上前端


以上五個步驟 前三步都有建立/更新是由於DOM/CSSOM/渲染樹可能在第一次繪畫後屢次更新 好比JS修改了DOM/CSS 佈局和繪畫也會被重複執行 除了DOM/CSSOM更新緣由外 圖片下載完成後也須要調用佈局和繪畫來更新網頁web

解析HTML文件的過程

1. 建立Document對象, 開始解析web頁面。解析HTML元素和他們的文本內容後添加Element對象和Text節點到文檔中。這個階段的document.readyState = 'loading';

2. 遇到link外部的css,建立線程加載,並繼續解析文檔。chrome

3. 遇到script外部的js,而且沒有設置async/defere,瀏覽器加載,並阻塞, 等待js加載完成並執行該腳本,而後繼續解析文檔。

4. 遇到script外部的js,而且設置async/defere,瀏覽器建立線程加載,並繼續解析文檔。對於async屬性的腳本,腳本加載完成後當即執行。(異步禁止使用document.write())前端工程化

5. 遇到img等,先正常解析dom結構,而後瀏覽器異步加載src,並繼續解析文檔。

6. 當文檔解析完成後,document.readyState = 'interactive' // domTree剛創建api

7. 文檔解析完成後,因此設置有defere的腳本會按照順序執行(注意與async的不一樣,但一樣禁止使用document.write())。

8. document對象觸發DOMContentLoaded事件,這也標誌着程序執行從同步腳本執行階段,轉化爲事件驅動階段 // 能夠監聽用戶的輸入事件/監聽事件。數組

9. 當全部的async的腳本加載完成並執行後,img等加載完成後 document.readyState = 'complete',window對象觸發Load事件。

10. 今後,以異步響應方式處理用戶輸入,網絡事件等 瀏覽器

分三步
1.建立Document對象
2.解析文檔
3.文檔加載完並執行完緩存

思考解析HTML文件中引起的問題?

1. 加載JS和CSS會阻塞瀏覽器的渲染嗎 下載JS和CSS會阻塞嗎
2. js加載會阻塞dom的解析嗎,js加載會阻塞dom的渲染嗎 ?
3. css加載會阻塞dom的解析嗎,css加載會阻塞dom的渲染嗎 ?
4. 爲何生成了CSSOM樹這樣的結構?

加載JS和CSS會阻塞瀏覽器的渲染嗎 下載JS和CSS會阻塞嗎

加載JS會阻塞瀏覽器渲染 加載CSS不會阻塞瀏覽器渲染 由於CSS加載是異步的

下載JS和CSS不會阻塞瀏覽器渲染 由於加載有個下載和解析的過程 而下載只是下載這個文件 不會讀取裏面的內容

js加載會阻塞dom的解析嗎,js加載會阻塞dom的渲染嗎 ?

js會阻塞dom的解析 但js不會阻塞dom的渲染 由於此時js代碼已經所有執行完成了

css加載會阻塞dom的解析嗎,css加載會阻塞dom的渲染嗎 ?

1. 整個頁面只引入一個外部css文件 css是不阻塞dom解析的 由於DOM解析和CSS解析是兩個並行的過程 可是css會阻塞dom渲染的 由於渲染樹是依賴於DOM樹和CSSOM樹 它必須等待到CSSOM樹構建完成 也就是CSS資源加載完成或者CSS資源加載失敗後 才能開始渲染 

2. css頁面後面還有外部js文件 css是阻塞了dom的解析的 這是主要是由於css後面還有js 考慮到js可能會改變css屬性 全部必須等到它前面的css執行完畢

img會阻塞dom的解析嗎,img會阻塞dom的渲染嗎 ?

一、沒有外部css文件 img對dom的解析沒有阻塞 可是會阻塞dom的渲染(而全部經過src屬性導入的元素,都會致使頁面渲染的堵塞。)

二、有外部css文件

爲何生成了CSSOM樹這樣的結構?

瀏覽器的優化方式/性能優化?

前端優化的途徑有不少,大體能夠分爲兩類:頁面級優化和代碼級優化。

頁面級優化有減小HTTP請求數、腳本的無阻塞加載、內聯腳本的位置優化等等。

代碼級優化有DOM操做優化、CSS選擇符優化、圖片優化以及HTML結構優化等等。

一丶頁面級優化

1. 減小HTTP請求數(最重要最有效)       

 一個完整的請求都須要DNS尋址丶與服務器創建鏈接丶發送數據丶等待服務器響應丶接受數據這樣一個漫長而複雜的過程 因爲瀏覽器進行併發請求的請求數都是有上限的 所以請求數多了之後 瀏覽器須要分批進行請求 所以會增長用戶的等待時間 會給用戶形成網站速度慢這樣的一個印象 即便可能用戶能看到的第一屏的資源都已經請求完了 可是瀏覽器的進度條一直在加載

(1)從設計實現層面簡化頁面

若是你的頁面和百度搜索的頁面同樣簡單,那麼也就不須要什麼優化操做了。所以保持頁面簡潔、減小資源的使用是最直接的。

(2)合理設置HTTP緩存

緩存的力量是強大的,恰當的設置緩存能夠大大減小HTTP請求

怎樣纔算是合理的設置?原則很簡單:能緩存越多越久越好。

例如:不多變化的圖片資源就能夠直接經過HTTP Header中的Expires設置一個很長的過時頭;變化不頻繁而又可能會變的資源可使用Last-Modified來作請求驗證。儘量的讓資源可以在緩存中待的更久。

(3)資源合併與壓縮

若是能夠的話,儘量的將外部腳本、樣式進行合併,儘量地合併爲一個。另外,CSS、JS、Image均可以用相應的工具進行壓縮,壓縮後每每能節省很多空間。或者使用Webpack等前端工程化工具來進行代碼的壓縮和去重。

(4)使用雪碧圖

雪碧圖又叫作精靈圖,咱們能夠把網站中須要用到的一些icon,所有放到一個圖片資源中,而後經過改變位置來獲取須要的圖片,這樣合併CSS圖片,就能夠大幅度減小HTTP請求數了。 

(5)內聯圖片使用 

data: URL scheme的方式將圖片嵌入到頁面或 CSS中,若是不考慮資源管理上的問題的話,不失爲一個好辦法。若是是嵌入頁面的話換來的是增大了頁面的體積,並且沒法利用瀏覽器緩存。使用在 CSS中的圖片則更爲理想一些。

(6) 懶加載

這條策略實際上並不必定能減小 HTTP請求數,可是卻能在某些條件下或者頁面剛加載時減小 HTTP請求數。對於圖片而言,在頁面剛加載的時候能夠只加載第一屏,當用戶繼續日後滾屏的時候才加載後續的圖片。這樣一來,假如用戶只對第一屏的內容感興趣時,那剩餘的圖片請求就都節省了。

首頁 曾經的作法是在加載的時候把第一屏以後的圖片地址緩存在 Textarea標籤中,待用戶往下滾屏的時候才 「惰性」 加載。

(6)瀑布流

其實懶加載並不能減小HTTP請求數,他只是能夠減小頁面剛加載的時候的HTTP請求數,總數是不變的。對於圖片而言,在頁面剛加載的時候可能只加載第一屏的圖片,隨着用戶的滾動纔會繼續加載後面的圖片資源,這種瀑布流的加載方式就能夠有效提升性能。

2. 將外部腳本放在底部

前文有談到,瀏覽器是能夠併發請求的,這一特色使得其可以更快的加載資源,然而外鏈腳本在加載時卻會阻塞其餘資源,例如在腳本加載完成以前,它後面的圖片、樣式以及其餘腳本都處於阻塞狀態,直到腳本加載完成後纔會開始加載。若是將腳本放在比較靠前的位置,則會影響整個頁面的加載速度從而影響用戶體驗。解決這一問題的方法有不少,而最簡單可依賴的方法就是將腳本儘量的日後挪,減小對併發下載的影響。

3. 併發執行內聯腳本

使用 script元素的defer 屬性(存在兼容性問題和其餘一些問題,例如不能使用document.write()、使用setTimeout ,此外,在HTML5中引入了 Web Workers的機制,偏偏能夠解決此類問題。 

4. 懶加載

只須要在須要資源的時候才加載資源,不須要的時候就不加載資源。

5. 將CSS放在 HEAD中

若是將 CSS放在其餘地方好比 BODY中,則瀏覽器有可能還未下載和解析到 CSS就已經開始渲染頁面了,這就致使頁面由無 CSS狀態跳轉到 CSS狀態,用戶體驗比較糟糕。除此以外,有些瀏覽器會在 CSS下載完成後纔開始渲染頁面,若是 CSS放在靠下的位置則會致使瀏覽器將渲染時間推遲。

6. 把js放到整個頁面的底部,另外一個方法是在script 標籤上加一個 defer屬性 保證讓瀏覽器把腳本下載出來後,而後等到頁面渲染完畢再執行。(參考權威指南 js時間線)

7. CSS文件用link標籤加載 是阻塞狀態的,咱們可使用loadCss小工具庫來進行異步css文件加載,可是有一個問題是,所有異步加載css,頁面最開始呈現出的只是單純的html ,不是很好看 因此咱們要選定一個關鍵的css文件,用critical工具來自動提取壓縮關鍵的css. (百度自行查看使用方法)

8. 減小沒必要要的HTTP跳轉

對於以目錄形式訪問的HTTP連接,不少人都會忽略連接最後是否帶’/’,假如你的服務器對此區別對待的話,那麼你也須要注意了,這其中極可能隱藏了301跳轉,增長了多餘請求。

 9. 避免重複的資源請求

這種狀況主要是因爲在模塊化開發時,咱們的不一樣模塊之間可能有相同的部分,致使資源的重複請求

二丶 代碼級優化

1. DOM 

 DOM操做應該是腳本中最耗性能的一類操做

(1)HTMLCollection(HTML收集器,返回的是一個數組的內容信息)由於是這個集合並非一個靜態的集合,它表示的僅僅是一個特定的查詢,每次訪問該集合時都會從新執行這個 查詢從而更新查詢結果。所謂的「訪問集合」包括讀取集合的length屬性、訪問集合中的元素

(2)Reflow&Repaint 

 減小頁面的重繪和重排。

2. 慎用with

with會改變做用域鏈,有可能致使咱們的做用域鏈變長,致使查詢性能降低。

3. 避免使用eval和Function

每次 eval 或 Function 構造函數做用於字符串表示的源代碼時,腳本引擎都須要將源代碼轉換成可執行代碼。這是很消耗資源的操做—— 一般比簡單的函數調用慢 100倍以上。

4. 減小做用域鏈查找

若是在循環中須要訪問非本做用域下的變量的時候,請遍歷以前用局部變量緩存的變量,並在遍歷結束以後重寫這個緩存變量

5. 數據訪問

js中對直接量和局部變量的訪問時最快的,對對象屬性以及數組的訪問須要更大的開銷,當出現下面的狀況的時候,建議將數據放入局部變量:

(1)對任何對象屬性的訪問超過1次

(2)對任何數組成員的訪問次數超過1次

另外,要儘量的減小對對象以及數組的深度查找。

6. 字符串拼接

字符串的拼接儘量少的使用「+」,這種方式的效率是十分低下的,由於每次運行都會開闢新的內存並生成新的字符串變量,而後將拼接的結果賦值給新變量。

建議使用的是先轉化爲數組,而後經過數組的join方法來鏈接成字符串。不過因爲數組也有必定的開銷,所以就須要權衡一下,當拼接的字符串比較少的時候,能夠考慮用「+」的方式,比較多的時候就須要考慮用數組的join方法了。


重繪和重排:頁面有三個樹:DOMTree、CSSTree、renderTree。(實際上多於三個),renderTree上有兩個規則:repaint和reflow,重繪和重排。

重繪(repaint)是元素自身的位置和寬高不變,只改變顏色的之類的屬性而不會致使後面的元素位置的變化的時候,renderTree發生的動做。

重排(reflow)是元素自身的位置或者寬高改變了從而致使的整個頁面的大範圍移動的時候,renderTree發生的動做。因此咱們在DOM操做的時候,要儘可能避免重排。

瀏覽器緩存

1. cookie

什麼是cookie?

cookie是由服務端生成的 發送給User-Agent(通常是瀏覽器) (服務器告訴瀏覽器設置一下cookie) 瀏覽器會將cookie以key/value形式保存到某個目錄下的文本文件內 下次請求同一網站時就發送該cookie給服務器(前提是瀏覽器設置爲啓動cookie)

cookie就是一個小型文件(瀏覽器對cookie的內存大小是有限制的 --- 用來設置一些信息)

爲何會有cookie?

Web應用程序是使用HTTP協議傳輸數據的 HTTP協議是無狀態的協議 一旦數據交換完畢 客戶端和服務端的鏈接就會關閉 再次交換數據須要創建新的鏈接 這就意味着服務器沒法從鏈接上跟蹤會話

cookie的特色?

cookie有保質期

知足同源策略 (不一樣域的話能夠在服務端設置document.domain或path來實現共享)

cookie內存大小受限制(cookie有個數和大小的限制 大小通常是4K)

注意?

cookie在本地 能夠被更改的文件 敏感數據不要放在cookiel裏

// 本身封裝設置cookie的代碼
var manageCookie = {    setCookie: function(name, value, time) {        document.cookie = name + '=' + value + ';max-age' + time;        return this;    },    removeCookie: function(name) {        return this.setCookie(name, '', -1);    },    getCookie: function(name, callback) {        var allCookieArr = document.cookie.split('; ');        for(var i = 0; i < allCookieArr.length; i++) {            var itemCookieArr = allCookieArr[i].split('=');            if(itemCookieArr[0] === name) {                callback(itemCookieArr[1]);                return this;            }        }        callback(undefined);        return this;    }}複製代碼

2. http緩存

http緩存是基於HTTP協議的瀏覽器文件級緩存機制

即針對文件的重複請求狀況下 瀏覽器能夠根據協議頭判斷從服務器端請求文件仍是從本地讀取文件 chrome控制檯下的Frames即展現的是瀏覽器的http文件級緩存 

如下是瀏覽器緩存的這個機制流程 主要針對重複的http請求 在有緩存的狀況下判斷過程主要分爲3步

判斷expires 若是未過時 直接讀取http緩存文件 不發http請求 不然進入下一步

判斷是否含有etag 有則帶上if-none-match發送請求 未修改返回304 修改返回200 不然進入下一步 

判斷是否含有last-modified 有則帶上if-modifined-since發送請求 無效返回200 有效返回304 不然直接向服務器請求

若是經過etag和last-modifined判斷 即便返回304有至少有一次http請求 只不過返回的是304的返回內容 而不是文件內容 因此合理設置實現expires參數能夠減小較多的瀏覽器請求

3. localstorage

localStorage是HTML5的一種新的本地緩存方案 目前用的比較多 通常用來存儲Ajax返回的數據 加快下次頁面打開時的渲染速度

經常使用API

localStorage.setItem(key, value); // 設置記錄

localStorage.getItem(key); // 得到記錄

localStorage.removeItem(key); // 刪除該域名下單條記錄

localStorage.clear(); // 刪除該域名下全部記錄

注意: localStorage大小有限制 不適合存放過多的數據 若是數據存放超過最大限制會報錯 並移除最早保存的數據

4. sesstionStorage

sesssionStorage和localStorage相似 可是瀏覽器關閉則會所有關閉 api和localStorage相同


.......未完待續

你的點贊是我持續輸出的動力 但願能幫助到你們 互相學習 有任何問題下面留言 必定回覆

相關文章
相關標籤/搜索