前端開發需要了解的瀏覽器通識

久宇詩發表於2021-12-02

瀏覽器通識

一、瀏覽器架構

1、單程式瀏覽器時代

2007年之前,市面上瀏覽器都是單程式的,在同一個程式裡會存在網路、外掛、JavaScript執行環境、渲染引擎和頁面等。
缺點

  1. 不穩定:一個節點崩潰,整個瀏覽器崩潰
  2. 不流暢:執行在同一個執行緒,需要重上到下一次完成
  3. 不安全:通過瀏覽器的漏洞來獲取系統許可權,可以對你的電腦做一些惡意的事情

2、多程式瀏覽器時代

新的Chrome瀏覽器包括:

  1. 1個瀏覽器(Browser)主程式:介面顯示、使用者互動、子程式管理,同時提供儲存等功能
  2. 1個 GPU 程式:UI介面都選擇採用GPU來繪製
  3. 1個網路(NetWork)程式:網路資源載入
  4. 多個渲染程式:將 HTML、CSS 和 JavaScript 轉換為使用者可以與之互動的網頁
  5. 多個外掛程式:負責外掛的執行
    瀏覽器是多程式的優點
  6. 一個頁面崩潰不會影響到整個瀏覽器
  7. 多程式可以充分利用現代 CPU 多核的優勢。
  8. 方便使用沙盒模型隔離外掛等程式,提高瀏覽器的穩定性。

3、Chrome 開啟一個頁面需要啟動多少程式?分別有哪些程式?

  • 開啟 1 個頁面至少需要 1 個網路程式、1 個瀏覽器程式、1 個 GPU 程式以及 1 個渲染程式,共 4 個;
  • 最新的 Chrome 瀏覽器包括:1 個瀏覽器(Browser)主程式、1 個 GPU 程式、1 個網路(NetWork)程式、多個渲染程式和多個外掛程式。

二、javascript單執行緒

1、為什麼採用單執行緒

主要用途是與使用者互動,以及操作DOM。如果JavaScript是多執行緒的,會帶來很多複雜的問題。
Web Worker:為 JavaScript 創造多執行緒環境,允許主執行緒建立 Worker 執行緒,將一些任務分配給後者執行。但是子執行緒完全受主執行緒控制,且不得操作DOM

2、瀏覽器核心中執行緒之間的關係

  1. GUI渲染執行緒和JS引擎執行緒互斥
  2. JS阻塞頁面載入:js如果執行時間過長就會阻塞頁面

3、程式和執行緒又是什麼呢

程式:是 CPU 資源分配的最小單位(是能擁有資源和獨立執行的最小單位)。
執行緒:是 CPU 排程的最小單位(是建立在程式基礎上的一次程式執行單位)。

4、任務佇列

JS 是單執行緒的,同步執行任務會造成瀏覽器的阻塞,所以我們將 JS 分成一個又一個的任務,通過不停的迴圈來執行事件佇列中的任務。

  • 單執行緒就意味著,所有任務都要排隊執行,前一個任務結束,才會執行後一個任務。
  • 如果當前執行緒空閒,並且佇列為空,那每次加入佇列的函式將立即執行。

三、渲染機制

1. 瀏覽器如何渲染網頁

瀏覽器渲染一共有五步

  1. 處理 HTML 並構建 DOM 樹。
  2. 處理 CSS構建 CSSOM 樹。
  3. 將 DOM 與 CSSOM 合併成一個渲染樹。
  4. 根據渲染樹來佈局,計算每個節點的位置。
  5. 呼叫 GPU 繪製,合成圖層,顯示在螢幕上

第四步和第五步是最耗時的部分,這兩步合起來,就是我們通常所說的渲染

  1. 在構建 CSSOM 樹時,會阻塞渲染,直至 CSSOM樹構建完成
  2. 當 HTML 解析到 script 標籤時,會暫停構建 DOM,完成後才會從暫停的地方重新開始

四、快取機制

1、常見 http 快取的型別

  1. 私有/瀏覽器/本地快取
  2. 代理快取

2、快取的好處

  1. 減少了冗餘的資料傳輸,減少網費
  2. 減少伺服器端的壓力
    W3. eb 快取能夠減少延遲與網路阻塞,進而減少顯示某個資源所用的時間
  3. 加快客戶端載入網頁的速度

3、瀏覽器快取總結

瀏覽器快取分為強快取協商快取

強快取

對一個網站而言,CSS、JavaScript、圖片等靜態資源更新的頻率都比較低,而這些檔案又幾乎是每次HTTP請求都需要的,如果將這些檔案快取在瀏覽器中,可以極好的改善效能。

通過設定http頭中的cache-control和expires的屬性,可設定瀏覽器快取,將靜態內容設為永不過期,或者很長時間後才過期。

1、Cache-Control
Cache-Control屬性是在伺服器端配置的,不同的伺服器有不同的配置,apache、nginx、IIS、tomcat等配置都不盡相同。
以Apache為例,在http.conf中做如下配置:

<filesMatch ”.(jpg|jpeg|png|gif|ico)$”>
	Header set Cache Control max-age=16768000,public
</filesMatch>
<filesMatch ”.(css|js)$”>
	Header set Cache Control max-age=2628000,public
</filesMatch>

問題:瀏覽器快取的資源,若又想更新資源,如何實現?
解決:通過修改該資源的名稱來實現。修改了資源名稱,瀏覽器會當做不同的資源。
Cache-Control相關屬性
no-cache:不使用本地快取。
no-store:直接禁止遊覽器快取資料,
public:可以被所有的使用者快取,
private:只能被終端使用者的瀏覽器快取,
max-age:從當前請求開始,
must-revalidate,當快取過期時,

2、Expires
Expires屬性也是在服務端配置的,具體的配置也根據伺服器而定。
問題:可能存在客戶端時間跟服務端時間不一致的問題。
解決:建議Expires結合Cache-Control一起使用。

Cache-Control: public
Expires: Wed, Jan 10 2018 00:27:04 GMT

過程

  • 第一次瀏覽器傳送請求給伺服器時,此時瀏覽器還沒有本地快取副本,伺服器返回資源給瀏覽器,響應碼是200 OK,瀏覽器收到資源後,把資源和對應的響應頭一起快取下來
  • 第二次瀏覽器準備傳送請求給伺服器時候,瀏覽器會先檢查上一次服務端返回的響應頭資訊中的Cache-Control,它的值是一個相對值,單位為秒,表示資源在客戶端快取的最大有效期,過期時間為第一次請求的時間減去Cache-Control的值,過期時間跟當前的請求時間比較,如果本地快取資源沒過期,那麼命中快取,不再請求伺服器
  • 如果沒有命中,瀏覽器就會把請求傳送給伺服器,進入快取協商階段。

協商快取

覽器在第一次訪問頁面時向伺服器請求資源,並快取起來,下次再訪問時會判斷在快取中是否已有該資源且有沒有更新過,如果已有該資源且未更新過,則直接從瀏覽器快取中讀取。

原理:
通過HTTP 請求頭中的 If-Modified-Since(If-No-Match) 和響應頭中的Last-Modified(ETag)來實現
HTTP請求把 If-Modified-Since(If-No-Match)傳給伺服器
伺服器將其與Last-Modified(ETag)對比,若相同,則檔案沒有被改動過,則返回304,直接瀏覽器快取中讀取資源即可。

快取位置

  • Service Worker
  • Memory Cache
  • Disk Cache
  • Push Cache

Service Worker

離線快取: 這個應用場景比如PWA,它借鑑了Web Worker思路,由於它脫離了瀏覽器的窗體,因此無法直接訪問DOM。它能完成的功能比如:離線快取、訊息推送和網路代理,其中離線快取就是Service Worker Cache。

Memory Cache

記憶體快取:從效率上講它是最快的,從存活時間來講又是最短的,當渲染程式結束後,記憶體快取也就不存在了。

Disk Cache

儲存在磁碟中的快取:從存取效率上講是比記憶體快取慢的,優勢在於儲存容量和儲存時長。

Push Cache

推送快取:這算是瀏覽器中最後一道防線吧,它是HTTP/2的內容

六、瀏覽器儲存

  1. 短暫性儲存:我們只需要將資料存在記憶體中,只在執行時可用
  2. 永續性儲存:可以分為 瀏覽器端 與 伺服器端
    • 瀏覽器:
      1. cookie: 通常用於儲存使用者身份,登入狀態等
      2. localStorage / sessionStorage: 長久儲存/視窗關閉刪除, 體積限制為 4~5M
      3. indexDB:瀏覽器提供的本地資料庫
    • 伺服器:
      1. 分散式快取 redis
      2. 資料庫

儲存大小:
cookie資料大小不能超過4k
sessionStorage和localStorage雖然也有儲存大小的限制,但比cookie大得多,可以達到5M或更大

有效期時間:
localStorage 儲存持久資料,瀏覽器關閉後資料不丟失除非主動刪除資料
sessionStorage 資料在當前瀏覽器視窗關閉後自動刪除
cookie 設定的cookie過期時間之前一直有效,即使視窗或瀏覽器關閉

七、跨域處理方案

九種實用的前端跨域處理方案

八、安全

網站安全問題彙總

九、PWA漸進式web應用--離線儲存

PWA漸進式web應用

十、DOM節點操作

JavaScript之BOM和DOM及其相容操作詳細總結
(1)建立新節點

createDocumentFragment()    //建立一個DOM片段
createElement()   //建立一個具體的元素
createTextNode()   //建立一個文字節點

(2)新增、移除、替換、插入

appendChild(node)
removeChild(node)
replaceChild(new,old)
insertBefore(new,old)

(3)查詢

getElementById();
getElementsByName();
getElementsByTagName();
getElementsByClassName();
querySelector();
querySelectorAll();

(4)屬性操作

getAttribute(key);
setAttribute(key, value);
hasAttribute(key);
removeAttribute(key);

十一、頁面載入過程

  1. 當我們開啟網址的時候,瀏覽器會從伺服器中獲取到 HTML 內容

  2. 瀏覽器獲取到 HTML 內容後,就開始從上到下解析 HTML 的元素

  3. <head>元素內容會先被解析,此時瀏覽器還沒開始渲染頁面

  4. 當瀏覽器解析到這裡時(步驟 3),會暫停解析並下載 JavaScript 指令碼

  5. 當 JavaScript 指令碼下載完成後,瀏覽器的控制權轉交給 JavaScript 引擎。當指令碼執行完成後,控制權會交回給渲染引擎,渲染引擎繼續往下解析 HTML 頁面

  6. 此時<body>元素內容開始被解析,瀏覽器開始渲染頁面]

js延遲載入的方式有哪些

  1. 將 js 指令碼放在文件的底部,來使 js 指令碼儘可能的在最後來載入執行
  2. 給 js 指令碼新增 defer 屬性,這個屬性會讓指令碼的載入與文件的解析同步解析,然後在文件解析完成後再執行這個指令碼檔案,這樣的話就能使頁面的渲染不被阻塞。多個設定了 defer 屬性的指令碼按規範來說最後是順序執行的,但是在一些瀏覽器中可能不是這樣
  3. 給 js 指令碼新增 async屬性,這個屬性會使指令碼非同步載入,不會阻塞頁面的解析過程,但是當指令碼載入完成後立即執行 js指令碼,這個時候如果文件沒有解析完成的話同樣會阻塞。多個 async 屬性的指令碼的執行順序是不可預測的,一般不會按照程式碼的順序依次執行
  4. 動態建立 DOM 標籤的方式,我們可以對文件的載入事件進行監聽,當文件載入完成後再動態的建立 script 標籤來引入 js 指令碼

十二、輸入url到展示過程

基礎版本

  • 瀏覽器根據請求的URL交給DNS域名解析,找到真實IP,向伺服器發起請求;
  • 伺服器交給後臺處理完成後返回資料,瀏覽器接收檔案(HTML、JS、CSS、圖象等);
  • 瀏覽器對載入到的資源(HTML、JS、CSS等)進行語法解析,建立相應的內部資料結構(如HTML的DOM);
  • 載入解析到的資原始檔,渲染頁面,完成。
  1. 從瀏覽器接收url到開啟網路請求執行緒(這一部分可以展開瀏覽器的機制以及程式與執行緒之間的關係)

  2. 開啟網路執行緒到發出一個完整的HTTP請求(這一部分涉及到dns查詢,TCP/IP請求,五層因特網協議棧等知識)

  3. 從伺服器接收到請求到對應後臺接收到請求(這一部分可能涉及到負載均衡,安全攔截以及後臺內部的處理等等)

  4. 後臺和前臺的HTTP互動(這一部分包括HTTP頭部、響應碼、報文結構、cookie等知識,可以提下靜態資源的cookie優化,以及編碼解碼,如gzip壓縮等)

  5. 單獨拎出來的快取問題,HTTP的快取(這部分包括http快取頭部,ETag,catch-control等)

  6. 瀏覽器接收到HTTP資料包後的解析流程(解析html-詞法分析然後解析成dom樹、解析css生成css規則樹、合併成render樹,然後layout、painting渲染、複合圖層的合成、GPU繪製、外鏈資源的處理、loaded和DOMContentLoaded等)

  7. CSS的視覺化格式模型(元素的渲染規則,如包含塊,控制框,BFC,IFC等概念)

  8. JS引擎解析過程(JS的解釋階段,預處理階段,執行階段生成執行上下文,VO,作用域鏈、回收機制等等)

  9. 其它(可以擴充不同的知識模組,如跨域,web安全,hybrid模式等等內容)

相關文章