浏览器相关知识3
內容整理來自極客時間李兵老師所講專欄《瀏覽器工作原理與實踐》
極客時間
-
css是如何影響首次白屏時間的?
解析HTML -》下載css -》下載js -》生成cssom -》執行js -》生成布局樹 -》繪制頁面
-
如何系統地優化頁面?
- 加載階段
通過分析network中關鍵資源(html文件 js文件 css文件)的大小,個數,只找到一個可能性能問題:html文件是128kb比較大,網站本身已經開啟gzip http2 多個靜態資源域名、開啟緩存等多個優化手段。 - 交互階段
新浪首頁頁面加載完成后,滾動頁面查看次屏頁面,沒有太多的交互,查看performance沒有發現太明顯的性能問題。 - 一個頁面從生命周期的維度主要分為三個階段:加載階段、交互階段、關閉階段。
3.1 加載階段影響網頁首次渲染的關鍵資源幾個指標:個數、大小、RTT(round trip time)。通常一個HTTP的數據包在14kb左右。
3.2 交互階段的優化主要是指渲染進程渲染幀速度。如何讓單個幀生成的速度變快呢?
3.2.1 減少JavaScript腳本執行時間
3.2.2 避免強制同步布局,添加 刪除dom后計算樣式布局是在另外一個任務中執行的,這時候獲取樣式信息,會將其變成同步任務。
3.2.3 避免布局抖動
3.2.4 合理利用CSS合成動畫(標識 will-change 單獨生成一個圖層)
3.2.5 避免頻繁的垃圾回收。(盡量避免臨時垃圾數據,優化存儲結構,避免小顆粒對象產生) -
PWA
PWA提出兩種解決方案:通過引入Service Worker來試著解決離線存儲和消息推送的問題,通過引入manifest.json來解決一級入口的問題,前提是要使站點支持Service Worker,首先必要的一步就是要站點升級到HTTPS。
- Service Worker
主要思想就是在頁面和網絡之間增加一個攔截器,用來緩存和攔截請求
-
WebComponent
- WebComponent是一套技術的組合,具體涉及了Custom elements(自定義元素)、Shadow Dom(影子DOM)和HTML templates(HTML模板)
- 如何創建?
2.1 查找模板的內容 const content = document.querySelector(‘xxx’).content
2.2 創建影子DOM const shadowDom = this.attachShadow({mode:open})
2.3 再將模板添加到影子DOM上 shadowDom.appendChild(content.cloneNode(true))
2.4 定義組件 customEelments.define(‘組件名’,xxx) - 瀏覽器是如何實現影子DOM?
3.1 影子DOM中的元素對于整個網頁是不可見的
3.2 影子DOM的css不會影響到整個網頁的CSSOM,影子DOM內部的CSS只對內部的元素起作用 -
HTTP性能優化
- HTTP/0.9
1.1 因為 HTTP 都是基于 TCP 協議的,所以客戶端先要根據 IP 地址、端口和服務器建立 TCP 連接,而建立連接的過程就是 TCP 協議三次握手的過程。
1.2 建立好連接之后,會發送一個 GET 請求行的信息,如GET /index.html用來獲取 index.html。
1.3 服務器接收請求信息之后,讀取對應的 HTML 文件,并將數據以 ASCII 字符流返回給客戶端。
- HTTP/1.0
引入請求頭和響應頭,他們都是以key-value形式存在。
2.1 如何支持多種不同類型數據?(請求頭)
2.1.1 首先,瀏覽器需要知道服務器返回的數據是什么類型的,然后瀏覽器才能根據不同的數據類型做針對性的處理。(如:accept:text/html)
2.1.2 其次,由于萬維網所支持的應用變得越來越廣,所以單個文件的數據量也變得越來越大。為了減輕傳輸性能,服務器會對數據進行壓縮后再傳輸,所以瀏覽器需要知道服務器壓縮的方法。(如:accept-encoding:gzip,deflate,br)
2.1.3 再次,由于萬維網是支持全球范圍的,所以需要提供國際化的支持,服務器需要對不同的地區提供不同的語言版本,這就需要瀏覽器告訴服務器它想要什么語言版本的頁面。(如:accept-Charset:ISO-8859-1,utf-8)
2.1.4 最后,由于增加了各種不同類型的文件,而每種文件的編碼形式又可能不一樣,為了能夠準確地讀取文件,瀏覽器需要知道文件的編碼類型。(accept-language:zh-CN,zh)
2.2 如何支持多種不同類型數據?(響應頭)
2.2.1 服務器接收到瀏覽器發送過來的請求頭信息之后,會根據請求頭的信息來準備響應數據。不過有時候會有一些意外情況發生,比如瀏覽器請求的壓縮類型是 gzip,但是服務器不支持 gzip,只支持 br 壓縮。(content-encoding:br)
2.2.2 Content-type:text/html;charset=utf-8
2.3 有的請求服務器可能無法處理,或者處理出錯,這時候就需要告訴瀏覽器服務器最終處理該請求的情況,這就引入了狀態碼。狀態碼是通過響應行的方式來通知瀏覽器的。
2.4 為了減輕服務器的壓力,在 HTTP/1.0 中提供了 Cache 機制,用來緩存已經下載過的數據。
2.5 服務器需要統計客戶端的基礎信息,比如 Windows 和 macOS 的用戶數量分別是多少,所以 HTTP/1.0 的請求頭中還加入了用戶代理的字段。 - HTTP/1.1
3.1 改進持久連接,它的特點是在一個 TCP 連接上可以傳輸多個 HTTP 請求,只要瀏覽器或者服務器沒有明確斷開連接,那么該 TCP 連接會一直保持。
3.2 隊頭阻塞問題,持久連接雖然能減少 TCP 的建立和斷開次數,但是它需要等待前面的請求返回之后,才能進行下一次請求。如果 TCP 通道中的某個請求因為某些原因沒有及時返回,那么就會阻塞后面的所有請求。
3.3 Host字段,在 HTTP/1.0 中,每個域名綁定了一個唯一的 IP 地址,因此一個服務器只能支持一個域名。但是隨著虛擬主機技術的發展,需要實現在一臺物理主機上綁定多個虛擬主機,每個虛擬主機都有自己的單獨的域名,這些單獨的域名都公用同一個 IP 地址。
3.4 Chunk transfer機制,服務器會將數據分割成若干個任意大小的數據塊,每個數據塊發送時會附上上個數據塊的長度,最后使用一個零長度的塊作為發送數據完成的標志。這樣就提供了對動態內容的支持。
3.5 客戶端Cookie、安全機制 -
如何提升網絡速度?HTTP2
- HTTP/1.1 效率問題
1.1 TCP的慢啟動
一旦一個 TCP 連接建立之后,就進入了發送數據狀態,剛開始 TCP 協議會采用一個非常慢的速度去發送數據,然后慢慢加快發送數據的速度,直到發送數據的速度達到一個理想狀態,我們把這個過程稱為慢啟動。
1.2 多條TCP連接競爭寬帶
因為有的 TCP 連接下載的是一些關鍵資源,如 CSS 文件、JavaScript 文件等,而有的 TCP 連接下載的是圖片、視頻等普通的資源文件,但是多條 TCP 連接之間又不能協商讓哪些關鍵資源優先下載,這樣就有可能影響那些關鍵資源的下載速度了。
1.3 隊頭阻塞
雖然能公用一個 TCP 管道,但是在一個管道中同一時刻只能處理一個請求,在當前的請求沒有結束之前,其他的請求只能處于阻塞狀態。這意味著我們不能隨意在一個管道中發送請求和接收內容。 - HTTTP/2帶來的提升
2.1 多路復用
一個域名只使用一個 TCP 長連接和消除隊頭阻塞問題。
2.2 實現原理
添加了一個二進制分幀層
2.2.1 首先,瀏覽器準備好請求數據,包括了請求行、請求頭等信息,如果是 POST 方法,那么還要有請求體。
2.2.2 這些數據經過二進制分幀層處理之后,會被轉換為一個個帶有請求 ID 編號的幀,通過協議棧將這些幀發送給服務器。
2.2.3 服務器接收到所有幀之后,會將所有相同 ID 的幀合并為一條完整的請求信息。
2.2.4 然后服務器處理該條請求,并將處理的響應行、響應頭和響應體分別發送至二進制分幀層。
2.2.5 同樣,二進制分幀層會將這些響應數據轉換為一個個帶有請求 ID 編號的幀,經過協議棧發送給瀏覽器。
2.2.6 瀏覽器接收到響應幀之后,會根據 ID 編號將幀的數據提交給對應的請求。 - HTTP/2其他特性
3.1 可以設置請求的優先級
HTTP/2 提供了請求優先級,可以在發送請求時,標上該請求的優先級,這樣服務器接收到請求之后,會優先處理優先級高的請求。
3.2 服務器推送
HTTP/2 還可以直接將數據提前推送到瀏覽器。
3.3 頭部壓縮 -
甩掉TCP、TLS的包袱,構建高效網絡?HTTP3
- TCP隊頭阻塞
在TCP傳輸過程中,由于單個數據包的丟失而造成的阻塞稱為TCP上的隊頭阻塞。 - TCP建立連接延時
我們把從瀏覽器發送一個數據包到服務器,再從服務器返回數據包到瀏覽器的整個往返時間稱為 RTT。若還存在使用TSL協議,則這樣就需要有兩個握手延遲過程。 - TCP協議僵化
中間設備的僵化以及操作系統原因 - QUIC協議
基于 UDP 實現了類似于 TCP 的多路數據流、傳輸可靠性等功能,我們把這套功能稱為 QUIC 協議。
QUIC協議可以看成集成了“TCP+HTTP2的多路復用+TLS協議“。
-
xmlHttpRequest為啥不能跨域?
- 同源策略、CSP 和 CORS 之間的關系:
- 同源策略就是說同源頁面隨你瞎搞,但是不同源之間想瞎搞只能通過瀏覽器提供的手段來搞
- 比如說
3.1. 讀取數據和操作 DOM 要用跨文檔機制
3.2. 跨域請求要用 CORS 機制
3.3. 引用第三方資源要用 CSP -
跨站腳本攻擊(XSS): 為啥Cookie中有HttpOnly屬性?
- 存儲型XSS攻擊
首先黑客利用站點漏洞將一段惡意 JavaScript 代碼提交到網站的數據庫中;
然后用戶向網站請求包含了惡意 JavaScript 腳本的頁面;
當用戶瀏覽該頁面的時候,惡意腳本就會將用戶的 Cookie 信息等數據上傳到服務器。 - 反射型XSS攻擊
惡意 JavaScript 腳本屬于用戶發送給網站請求中的一部分,隨后網站又把惡意 JavaScript 腳本返回給用戶。當惡意 JavaScript 腳本在用戶頁面中被執行時,黑客就可以利用該腳本做一些惡意操作。 - 基于DOM的XSS攻擊
基于 DOM 的 XSS 攻擊是不牽涉到頁面 Web 服務器的。具體來講,黑客通過各種手段將惡意腳本注入用戶的頁面中,比如通過網絡劫持在頁面傳輸過程中修改 HTML 頁面的內容,這種劫持類型很多,有通過 WiFi 路由器劫持的,有通過本地惡意軟件來劫持的,它們的共同點是在 Web 資源傳輸過程或者在用戶使用頁面的過程中修改 Web 頁面的數據。 - 如何防止XSS攻擊
4.1 服務器對輸入腳本進行過濾或者轉碼
服務器對關鍵提交數據進行轉碼:過濾掉敏感代碼或者將敏感代碼轉碼
4.2 充分利用CSP
通過HTTP頭信息的Content-Security-Policy設置比如script-src,object-src,style-src等內容或者通過meta標簽或者搭配Content-Security-Policy-Report-Only來使用<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:"> 4.3 使用Cookie的HttpOnly屬性 -
CSRF攻擊
- CSRF(Cross-site-request-forgery)跨站請求偽造
利用用戶的登錄狀態,并通過第三方的站點來做一些壞事。利用服務器的漏洞和用戶的登錄狀態來實施攻擊。 - 自動發起GET請求
利用圖片Img標簽,欺騙瀏覽器作非法請求 - 自動發起POST請求
利用form表單發起請求 - 引誘用戶點擊連接
- 發起CSRF攻擊的三個必要條件
5.1 目標站點一定要有CSRF漏洞
5.2 用戶要登錄過目標站點,并且在瀏覽器上保持有該站點的登錄狀態
5.3 需要用戶打開一個第三方站點 - 如何防范?
6.1 利用Cookie的SameSite屬性
在HTTP響應頭中,通過set-cookie字段設置Cookie時,可以帶上SameSite選項,如:set-cookie: 1P_JAR=2019-10-20-06; expires=Tue, 19-Nov-2019 06:36:21 GMT; path=/; domain=.google.com; SameSite=none 6.1.1 Strict(嚴格,完全禁止第三方Cookie)
6.1.2 Lax (但如果在第三方站點中使用 Post 方法,或者通過 img、iframe 等標簽加載的 URL,這些場景都不會攜帶 Cookie)
6.1.3 None(任何情況均發送)
6.2 驗證請求的來源站點
6.2.1 HTTP請求頭中的Referer字段 (包含路徑信息)
6.2.2 HTTP請求頭中的Origin字段 (不包含路徑信息)
6.3 CSRF Token -
安全沙箱:頁面和系統之間的隔離墻
安全沙箱是不能防止 XSS 或者 CSRF 一類的攻擊,
安全沙箱的目的是隔離渲染進程和操作系統,讓渲染進行沒有訪問操作系統的權利
XSS 或者 CSRF 主要是利用網絡資源獲取用戶的信息,這和操作系統沒有關系的 -
HTTPS:讓數據傳輸更安全
瀏覽器安全主要包括頁面安全、系統安全、傳輸安全三個部分。https主要保證傳輸過程的安全,從防止中間人竊取修改偽造的角度循序漸進的介紹了https的實現過程。
- 對稱加密傳輸(協商秘鑰的過程容易被竊取)
- 非對稱加密傳輸(服務端用私鑰加密的內容,可以通過它的公鑰進行解密)
- 非對稱加密交換秘鑰、對稱加密傳輸內容(DNS劫持 如何保證服務器是可信的)
- 引入CA權威機構保證服務器可信性。
數字證書的申請過程:服務器生成一對公鑰和私鑰,私鑰自己保存,通過公鑰+企業+網站信息去CA機構申請證書。CA機構通過全方位的驗證給這個網站頒發證書,證書內容包括企業信息、證書有效期、證書編號,以及自己私鑰加密上述信息的摘要、網站的公鑰。服務器就獲得了CA的認證。
瀏覽器認證證書過程:瀏覽器從服務器拿到網站的證書,通過CA的公鑰解密證書信息的摘要跟使用摘要算法計算企業信息等的摘要對比,如果一致則證明證書有效。如果證書CA是可靠的呢,通過給CA頒發證書的根CA驗證,通常操作系統中包括頂級CA證書(它們自己給自己簽名稱為自簽名證書,我們自己生成證書也是自簽名證書 只是它不是操作系統內置的)
總結
- 上一篇: 浏览器静态资源的版本控制新思路.强制更新
- 下一篇: 美团前端二面必会面试题(附答案)