瀏覽器之基礎 - 緩存 - 渲染(問答)

前陣子在一直準備面試,發現瀏覽器原理相關的問題經常被問到,大致關於基礎 / 緩存 / 渲染這三方面。爲了贏下和麪試官的 battle🤨,纔有了這篇總結。


什麼是跨域?爲什麼瀏覽器要使用同源策略?你有幾種方式可以解決跨域問題?瞭解預檢請求嘛?

瀏覽器的同源策略導致了跨域,同源策略屬於瀏覽器的安全機制,如果_**協議、域名、端口**_有一個不同就是跨域,請求會失敗。 同源策略主要是用於防範CSRF攻擊的。簡單點說,CSRF 攻擊是利用用戶的登錄態發起惡意請求。   解決跨域的方法: JSONP/CORS/代理服務

1.JSONP

JSONP 的原理很簡單,就是利用 <script> 標籤沒有跨域限制的漏洞。通過 <script> 標籤指向一個需要訪問的地址並提供一個回調函數來接收數據當需要通訊時。JSONP 使用簡單且兼容性不錯,但是隻限於 get 請求。

<script src="http://domain/api?param1=a¶m2=b&callback=jsonp"></script>
<script>
    function jsonp(data) {
        console.log(data)
    }
</script>

  2.CORS

CORS 需要瀏覽器和後端同時支持。瀏覽器會自動進行 CORS 通信,實現 CORS 通信的關鍵是後端。只要後端實現了 CORS,就實現了跨域。 服務端設置 Access-Control-Allow-Origin 就可以開啓 CORS。 該屬性表示哪些域名可以訪問資源,如果設置通配符則表示所有網站都可以訪問資源。 雖然CORS和前端沒什麼關係,但是需要知道通過這種方式解決跨域問題的話,發送的請求會分別爲簡單請求和複雜請求。 對於複雜請求來說,首先會發起一個預檢請求,該請求是 option 方法的,通過該請求來知道服務端是否允許跨域請求。   3. 代理 通過代理把前端請求的域名轉發到後端域名上,隱藏真實的服務端。可通過webpacknigix實現。


有幾種方式可以實現存儲功能,分別有什麼優缺點?什麼是 Service Worker?

cookie,localStorage,sessionStorage,indexDB皆可實現存儲

l5Gyve

cookie使用時需要注意_**安全性**_

J9T8ty


事件的觸發過程是怎麼樣的?知道什麼是事件代理嘛?

事件觸發有三個階段:

  1. window 往事件觸發處傳播,遇到註冊的捕獲事件會觸發
  2. 傳播到事件觸發處時觸發註冊的事件
  3. 從事件觸發處往 window 傳播,遇到註冊的冒泡事件會觸發

  一般來說,如果我們只希望事件只觸發在目標上,這時候可以使用 stopPropagation 來阻止事件的進一步傳播。   事件代理 如果一個節點中的子節點是動態生成的,那麼子節點需要註冊事件的話應該註冊在父節點上 事件代理的方式相較於直接給目標註冊事件來說,因爲不需要給子節點註銷事件,所以節省了內存。


瀏覽器緩存機制

  對於一個數據請求來說,可以分爲_**發起網絡請求、後端處理、瀏覽器響應**_ 三個步驟。瀏覽器緩存可以幫助我們在第一和第三步驟中優化性能。比如說直接使用緩存而不發起請求,或者發起了請求但後端存儲的數據和前端一致,那麼就沒有必要再將數據回傳回來,這樣就減少了響應數據。   接下來的內容中我們將通過以下幾個部分來探討瀏覽器緩存機制:   **緩存位置**:Service Worker > Memory Cache > Disk Cache > Push Cache > 網絡請求,以上表示優先級從大到小排序。

緩存策略: 強緩存和協商緩存,並且緩存策略都是通過設置 HTTP Header 來實現的。不細說了,至今還沒人問過。

實際場景應用緩存策略: 對於頻繁變動的資源:首先需要使用 Cache-Control: no-cache 使瀏覽器每次都請求服務器,然後配合 ETag 或者 Last-Modified 來驗證資源是否有效。這樣的做法雖然不能節省請求數量,但是能顯著減少響應數據大小。   對於代碼文件:現在都會使用工具來打包代碼,那麼我們就可以對文件名進行哈希處理,只有當代碼修改後纔會生成新的文件名。基於此,我們就可以給代碼文件設置緩存有效期一年 Cache-Control: max-age=31536000,這樣只有當 HTML 文件中引入的文件名發生了改變纔會去下載最新的代碼文件,否則就一直使用緩存。

目前還沒遇到面試官問這塊的知識點,性能優化方面還是圍繞webpack聊的比較多。


瀏覽器渲染原理

不同的瀏覽器有不同的渲染引擎,這裏主要說的是 Webkit 渲染引擎。

當我們打開一個網頁時,瀏覽器都會去請求對應的 HTML 文件。雖然平時我們寫代碼時都會分爲 JS、CSS、HTML 文件,也就是字符串,但是計算機硬件是不理解這些字符串的,所以在網絡中傳輸的內容其實都是 01 這些字節數據。當瀏覽器接收到這些字節數據以後,它會將這些字節數據轉換爲字符串,也就是我們寫的代碼。

當數據轉換爲字符串以後,瀏覽器會先將這些字符串通過詞法分析轉換爲標記token),這一過程在詞法分析中叫做標記化tokenization)。

那麼什麼是標記呢?簡單來說,標記還是字符串,是構成代碼的最小單位。這一過程會將代碼分拆成一塊塊,並給這些內容打上標記,便於理解這些最小單位的代碼是什麼意思。

當結束標記化後,這些標記會緊接着轉換爲 Node,最後這些 Node 會根據不同 Node 之前的聯繫構建爲一顆 DOM 樹。

以上就是瀏覽器從網絡中接收到 HTML 文件然後一系列的轉換過程,過程大致如下: 字節數據 => 字符串 => 標記(Token) => Node => DOM   在解析 HTML 文件的時候,瀏覽器還會遇到 CSS 和 JS 文件,這時候瀏覽器也會去下載並解析這些文件,解析 CSS 文件的過程與 HTML 文件極爲類似,最後會生成一顆 CSSOM樹。   當我們生成 DOM 樹和 CSSOM 樹以後,瀏覽器會將這兩棵樹組合爲渲染樹,然後根據渲染樹來進行佈局(也可以叫做迴流),然後調用 GPU 繪製,合成圖層,顯示在屏幕上。


除此之外,還有些零碎的知識點,因爲已經熟記於心就不做展開了,包括:

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://juejin.cn/post/6956504483299868686