No5.瀏覽器中的頁面

前段時間在《極客時間》上學了一個專欄,通篇略過,乾貨不少,但理解相當不夠透徹,於是計劃用幾周的時間,對本專欄內容用作者的總結以及自己的相對逐字理解,來個通篇的文字記錄學習,書讀百遍,其義自現。
本篇是這個專欄的第五章:《No5.瀏覽器中的頁面》。本章分爲八節。

21 | Chrome開發者工具:利用網絡面板做性能分析


本節首先對開發者工具的各個模塊進行了一個簡單介紹,然後重點講解的是NetWork面板。
網絡面板包括:控制器、過濾器、抓圖信息、時間線、詳細列表和下載信息概要六個區域構成。

1.控制器
  • “開始/暫停”抓包。
  • 全局搜索。
  • Disable cache:禁止從Cache中加載資源。
  • Online按鈕:模擬2G/3G 網絡,模擬弱網環境。
2.過濾器

過濾功能。

3.抓圖信息

抓圖信息區域,可以用來分析用戶等待頁面加載時間內所看到的內容,分析用戶實際的體驗情況。

4.時間線

時間線,主要用來展示 HTTP、HTTPS、WebSocket 加載的狀態和時間的一個關係,用於直觀感受頁面的加載過程。

5.詳細列表

詳細記錄了每個資源從發起請求到完成請求這中間所有過程的狀態,以及最終請求完成的數據信息.
Queuing:當瀏覽器發起一個請求的時候,會有很多原因導致該請求不能被立即執行,而是需要排隊等待。
Stalled: 在發起連接之前,還有一些原因可能導致連接過程被推遲,這個推遲就表現在面板中的 Stalled 上。
Proxy Negotiation:若使用代理服務器,會增加一個此階段。
Waiting (TTFB):通常也稱爲“第一字節時間”。 TTFB 是反映服務端響應速度的重要指標,對服務器來說,TTFB 時間越短,就說明服務器響應越快。
Content Download :這意味着從第一字節時間到接收到全部響應數據所用的時間。

6.下載信息概要

重點關注 DOMContentLoaded和Load兩個事件。

  • DOMContentLoaded:這個事件發生後,說明頁面已經構建好DOM了,即DOM需要的HTML、JavaScript、CSS等文件已下載完成了。
  • Load:說明瀏覽器已經加載了所有的資源(圖像、樣式等)。

22 | DOM樹:JavaScript是如何影響DOM樹構建的?


什麼是DOM

DOM 是表述 HTML 的內部數據結構,它會將 Web 頁面和 JavaScript 腳本連接起來,並過濾一些不安全的內容。

DOM樹如何生成

在渲染引擎內部,有一個叫 HTML 解析器(HTMLParser)的模塊,它的職責就是負責將 HTML 字節流轉換爲 DOM 結構。
HTML解析器過程是:網絡進程加載了多少數據,HTML解析器便解析多少數據。

JavaScript是如何影響DOM生成的
  • 在兩段 div 中間插入了一段 JavaScript 腳本:當HTML解析器解析到script標籤的時候會暫停DOM解析,去執行這段JS腳本。
  • 在頁面中引入 JavaScript文件:整個執行流程還是一樣的,執行到 JavaScript 標籤時,暫停整個 DOM 的解析,執行 JavaScript 代碼,不過這裏執行 JavaScript 時,需要先下載這段 JavaScript 代碼。這裏需要重點關注下載環境,因爲 JavaScript 文件的下載過程會阻塞 DOM 解析(Chrome瀏覽器做的一個主要優化是預解析操作)。
    另外也有一些相關的策略:比如使用 CDN 來加速 JavaScript 文件的加載,壓縮 JavaScript 文件的體積。如果 JavaScript 文件中沒有操作 DOM 相關代碼,就可以將該 JavaScript 腳本設置爲異步加載,通過 asyncdefer 來標記代碼.
  1. async:使用 async 標誌的腳本文件一旦加載完成,會立即執行.
  2. defer:使用了 defer 標記的腳本文件,需要在 DOMContentLoaded 事件之前執行.

通過上面的分析,我們知道了 JavaScript 會阻塞 DOM 生成,而樣式文件又會阻塞 JavaScript 的執行,所以在實際的工程中需要重點關注 JavaScript 文件和樣式表文件,使用不當會影響到頁面性能的。

23 | 渲染流水線:CSS如何影響首次加載時的白屏問題


CSS資源是頁面中非常重要的一環,本節首先站在渲染流水線的視角來介紹CSS是如何工作的、然後通過CSS工作流程來分分析性能瓶頸、最後討論如何減少首次加載時的白屏問題。

渲染流水線視角下的CSS

首先是發起頁面請求,網絡進程接收到返回的HTML數據,將其發送給渲染進程,渲染進程解析HTML數據並構建DOM。
需要特別注意下,請求 HTML 數據和構建 DOM 中間有一段空閒時間,這個空閒時間有可能成爲頁面渲染的瓶頸。

前面提到一嘴:Chrome瀏覽器做的一個主要優化是預解析操作。
因此,Chrome開啓這個預解析進程後,在遇到JavaScript或CSS文件後,會提前下載這些文件。
這裏也有一個空閒時間需要注意一下,就是在 DOM 構建結束之後、css 文件還未下載完成的這段時間內,渲染流水線無事可做,因爲下一步是合成佈局樹,而合成佈局樹需要 CSSOM 和 DOM,所以這裏需要等待 CSS 加載結束並解析成 CSSOM。

CSSOM的兩個作用:

  • 提供給 JavaScript 操作樣式表的能力.
  • 爲佈局樹的合成提供基礎的樣式信息。
影響頁面展示的因素以及優化策略

從發起 URL 請求開始,到首次顯示頁面的內容,在視覺上經歷的三個階段:

  1. 等請求發出去之後,到提交數據階段,這時頁面展示出來的還是之前頁面的內容。
  2. 提交數據之後渲染進程會創建一個空白頁面,我們通常把這段時間稱爲解析白屏,並等待 CSS 文件和 JavaScript 文件的加載完成,生成 CSSOM 和 DOM,然後合成佈局樹,最後還要經過一系列的步驟準備首次渲染.
  3. 等首次渲染完成之後,就開始進入完整頁面的生成階段了,然後頁面會一點點被繪製出來。

這裏重點關注第二個階段:
該階段的主要任務包括了:解析 HTML、下載 CSS、下載 JavaScript、生成 CSSOM、執行 JavaScript、生成佈局樹、繪製頁面一系列操作。
對應策略:

  • 通過內聯 JavaScript、內聯 CSS 來移除這兩種類型的文件下載,這樣獲取到 HTML 文件之後就可以直接開始渲染流程了。
  • 但並不是所有的場合都適合內聯,那麼還可以儘量減少文件大小,比如通過 webpack 等工具移除一些不必要的註釋,並壓縮 JavaScript 文件。
  • 還可以將一些不需要在解析 HTML 階段使用的 JavaScript 標記上 sync 或者 defer。
  • 對於大的 CSS 文件,可以通過媒體查詢屬性,將其拆分爲多個不同用途的 CSS 文件,這樣只有在特定的場景下才會加載特定的 CSS 文件。

24 | 分層和合成機制:爲什麼CSS動畫比JavaScript高效


在第五節的時候,我們知道DOM構建成功後還要經歷佈局、分層、繪製、合成、顯示等階段後才能顯示出漂亮的頁面。
這一節主要講解的是渲染引擎的分層和合成機制,作者說分層和合成機制代表了瀏覽器最爲先進的合成技術,請注意是最爲先進的.

顯示器是怎麼顯示圖像的

每個顯示器的固定刷新頻率通常是60HZ,即每秒更新60張圖片,更新的圖片都來自顯卡中一個叫前緩衝區的地方,,顯示器所做的任務很簡單,就是每秒固定讀取 60 次前緩衝區中的圖像,並將讀取的圖像顯示到顯示器上。
顯卡的作用:顯卡的職責就是合成新的圖像,並將圖像保存到後緩衝區中,一旦顯卡把合成的圖像寫到後緩衝區,系統就會讓後緩衝區和前緩衝區互換,這樣就能保證顯示器能讀取到最新顯卡合成的圖像。

幀 VS 幀率

渲染流水線生成的每一張圖片稱爲一幀,渲染流水線每秒更新了多少幀稱爲幀率。

如何生成一幀圖像

生成一幀圖像有三種方式:重排、重繪、合成。 這三種方式的渲染路徑不同,通常渲染路徑越長,生成圖像花費的時間越久。
這裏聚焦點在合成上 ,爲了提升每幀的渲染效率,Chrome 引入了分層和合成的機制,Chrome的合成技術用三個詞來概括:分層、分塊、合成。

分層和合成

你可以把一張網頁想象成是由很多個圖片疊加在一起的,每個圖片就對應一個圖層,將素材分解爲多個圖層的操作就稱爲分層。最後將這些圖層合併到一起的操作就稱爲合成。
在Chrome渲染流水線中,分層體現在生成佈局樹之後,渲染引擎根據佈局樹的特點將其轉化爲層樹,層樹是渲染流水線後續流程的基礎結構。
需要重點關注的是,合成操作是在合成線程上完成的,這也就意味着在執行合成操作時,是不會影響到主線程執行的。這就是爲什麼經常主線程卡住了,但是 CSS 動畫依然能執行的原因。

分塊

如果說分層是從宏觀上提升了渲染效率,那麼分塊則是從微觀層面提升了渲染效率。
在首次合成圖塊的時候使用一個低分辨率的圖片。

如何利用分層技術優化代碼

在寫 Web 應用的時候,你可能經常需要對某個元素做幾何形狀變換、透明度變換或者一些縮放操作,如果使用 JavaScript 來寫這些效果,會牽涉到整個渲染流水線,所以 JavaScript 的繪製效率會非常低下.
這時你可以使用 will-change 來告訴渲染引擎你會對該元素做一些特效變換,CSS 代碼如下:

    .box {
        will-change: transform, opacity;
    }

這段代碼就是提前告訴渲染引擎 box 元素將要做幾何變換和透明度變換操作,這時候渲染引擎會將該元素單獨實現一幀,等這些變換髮生時,渲染引擎會通過合成線程直接去處理變換,這些變換並沒有涉及到主線程,這樣就大大提升了渲染的效率。這也是 CSS 動畫比 JavaScript 動畫高效的原因.

25 | 頁面性能:如何系統地優化頁面?


本節所談論的頁面優化,其實就是讓頁面更快的顯示和響應。
通常一個頁面有三個階段:加載階段、交互階段和關閉階段。

  • 加載階段,是指從發出請求到渲染出完整頁面的過程,影響到這個階段的主要因素有網絡和 JavaScript 腳本。
  • 交互階段,主要是從頁面加載完成到用戶交互的整合過程,影響到這個階段的主要因素是 JavaScript 腳本。
  • 關閉階段,主要是用戶發出關閉指令後頁面所做的一些清理操作。
    這裏我們需要重點關注加載階段和交互階段,因爲影響到我們體驗的因素主要都在這兩個階段.
加載階段

並非所有的資源都會阻塞頁面的首次繪製,比如圖片、音頻、視頻等文件就不會阻塞頁面的首次渲染。而JavaScript、首次請求的HTML資源文件、CSS文件是會阻塞首次渲染的。把這些能阻塞頁面渲染的稱爲關鍵資源。基於關鍵資源,細化出三個影響頁面首次渲染的核心因素:

  • 第一個是關鍵資源個數。
  • 第二個是關鍵資源大小。
  • 第三個是請求關鍵資源需要多少個RTT(Round Trip Time).[通常1個HTTP的數據包在14KB左右,所以0.1M的頁面需要拆分成8個包來傳輸,也就是說需要8個RTT]。

然後針對核心因素,考慮優化方案:總的優化原則就是減少關鍵資源個數、降低關鍵資源大小、降低關鍵資源的RTT次數。

交互階段

交互階段的優化,一個大的原則就是讓單個幀的生成速度變快。

  1. 減少JavaScript腳本執行時間。
  2. 避免強制同步佈局。【所謂強制同步佈局,是指JavaScript強制將計算樣式和佈局操作提前到當前的任務中。】
  3. 避免佈局抖動。
  4. 合理利用CSS合成動畫。
  5. 避免頻繁的垃圾回收。

26 | 虛擬DOM:虛擬DOM和實際的DOM有何不同?


本節先聊一些DOM的缺陷,然後在此基礎上介紹虛擬DOM如何解決這些缺陷,最後站在雙緩存和MVC的視角來聊聊虛擬DOM。

DOM的缺陷

通過前面對DOM的學習,我們知道對於一些複雜的頁面或者目前使用非常多的單頁面應用來說,其DOM結構複雜,每次操作需要去不斷修改DOM樹,每次操作渲染引擎都需要進行重繪、重排或者合成操作,執行一次重排或者重繪操作是非常耗時的,這樣就帶來了性能問題。
所以就需要一直方式來減少JavaScript對DOM的操作,這時候虛擬DOM就上場了。

什麼是虛擬DOM

虛擬DOM要解決的事情:

  • 將頁面改變的內容應用到虛擬DOM上,而不是直接應用在DOM上。
  • 變化被應用到虛擬DOM上時,虛擬DOM並不急着去渲染頁面,而僅僅是調整虛擬DOM的內部狀態,這樣操作虛擬DOM的代價就變得非常輕了。
  • 在虛擬DOM收集到足夠的改變時,再把這些變化一次性應用到真實的DOM上。

接下來從雙緩存和MVC模型這兩個視角來聊聊虛擬DOM:

    1. 雙緩存

雙換粗是一種經典的思路,應用哎很多場合,能解決頁面無效刷新和閃屏的問題,虛擬DOM就是雙緩存思想的一種實現。
使用雙緩存,可以先將計算的中間結果存放到另一個緩衝區中,等全部的計算結束,該緩衝區已經存儲了完整的圖形,這樣使得整個圖像的輸出非常穩定。

  1. MVC模式
    基於MVC的設計思想廣泛地滲透到各種場合,且基於MVC又衍生出了很多其他模式(如MVP、MVVM),不過萬變不離其宗,它們的基礎框架都是基於MVC而來。站在MVC視角來理解虛擬DOM能讓你看到更爲“廣闊的世界”.

27 | 漸進式網頁應用(PWA):它究竟解決了Web應用的哪些問題?


PWA,全稱是Progressive Web App,漸進式網頁應用。

漸進式:

  • 站在Web應用開發者來說,PWA提供了一個漸進式的過度方案,讓普通站點逐步過度到Web應用。採取漸進式可以降低站點改造的代價,使得站點逐步支持各項新技術,而不是一步到位。
  • 站在技術角度來說,PWA技術也是一個漸進式的演化過程,在技術層面會一點點演進,比如逐漸提供更好的設備特性支持,不斷優化更加流暢的動畫效果,不斷讓頁面的加載速度變得更快,不斷實現本地應用的特性。
    可以這麼理解:PWA是一套理念,漸進式增強Web的優勢,並通過技術手段漸進式縮短和本地應用或者小程序的距離。
Web應用 VS 本地應用

相較於本地應用,Web應用缺陷:

  • 首先,Web應用缺少離線使用能力,在離線或者弱網環境下基本上是無法使用的。
  • 其次,Web應用還缺少了消息推送的能力。
  • 最後,Web缺少一級入口。

針對以上缺陷,PWA提出了兩種解決方案:通過引入Service Worker來試着解決離線存儲和消息推送的問題,通過引入manifest.json來解決一級入口的問題。

Service Worker

在2014年的時候,標準委員會就提出來Service Worker的概念,主要思想是在頁面和網絡之間增加一個攔截器,主要功能就是用來緩存資源和攔截請求。

設計思路:
爲避免JavaScript過多佔用頁面主線程時長的情況,瀏覽器實現了Web Worker的功能。Web Worker的目的是讓JavaScript能夠運行在頁面主線程之外,且只能執行一些與DOM無關的JS腳本。在Chrome中,Web Worker其實就是在渲染進程中開啓一個新線程,它的生命週期和頁面關聯。
"讓其運行在主線程之外"就是Service Worker來自Web Worker的一個核心思想。但需要在Web Worker的基礎上加上儲存功能。且Service Worker還需要會爲多個頁面提供服務,所以還不能把Service Worker和單個頁面綁定起來。
消息推送也是基於Service Worker來實現的。
最後,若要使站點支持Service Worker,首先必要的一步就是要將站點升級到HTTPS。

28 | WebComponent:像搭積木一樣構建Web應用


首先,本節介紹了組件化開發是程序員的剛需,所謂組件化就是功能模塊要實現高內聚、低耦合的特性。
不過由於 DOM 和 CSSOM 都是全局的,所以它們是影響了前端組件化的主要元素。
基於這個原因,就出現 WebComponent,它包含自定義元素、影子 DOM 和 HTML 模板三種技術,使得開發者可以隔離 CSS 和 DOM。
在此基礎上,還重點介紹了影子 DOM 到底是怎麼實現的。
關於 WebComponent 的未來如何,這裏我們不好預測和評判,但是有一點可以肯定,WebComponent 也會採用漸進式迭代的方式向前推進,未來依然有很多坑需要去填。

世界有多大,取決於你認識和見過多少人和事。

如有疑問請添加我的微信號:18231133236。歡迎交流!
更多內容,請訪問的我的個人博客:https://www.liugezhou.online.
您也可以關注我的個人公衆號:【Dangerous Wakaka】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章