正如前面寫的 瀏覽器中輸入URL後會發生什麼事情--超級詳細版 中介紹的一樣,一個 頁面的渲染過程 也涉及到了 很多的東西,以及進程之間的通信
1、網絡
- 網絡進程接收到了 一個 html 文件 之後,除了會判斷 content-type 之外,還會發生什麼呢?
- 首先,要知道的是 TCP 的通訊 並不是一次性的,而是一個包一個包發過來的
- 網絡進程也是如此,和 渲染進程建立了 通道之後,也是一個包一個包地發給渲染進程
2、渲染進程——解析
<head>
<style>
div{
font-size: 20px;
}
</style>
</head>
<body>
<div class="div1">div1</div>
<script>
document.querySelect('.div1').style.color = "red";
document.querySelect('.div2').style.color = "red";
</script>
<div class="div2">div2</div>
</body>
- 渲染進程 在接收到 文件之後,會將頁面清空,這裏就會出現一個白屏的 現象
- 渲染進程 開始 一點一點地 解析 數據包,然後生成 dom 樹
- 在這個過程之中,如果遇到了 內嵌的 css 或者 link 標籤上的 css 外鏈,那麼 繼續 解析 dom ,並行地下載 css 以及解析 cssom
- 那麼 是不是 css 就不會阻止 dom 的解析呢?
- 答案是 否定的,關鍵點 就在 js 上
- 看上面的那一段代碼,可以看到,js 是可以 讀取 一個 dom 的 css 的,也就是 讀取到 cssom 的
- 而衆所周知的事情是,js 執行 的時候 是會 阻止 dom 繼續解析的
- 所以 爲了 讀取到 一個 dom 的css ,這個時候的 js 會等 css 加載完,cssom 也創建完畢之後,纔開始執行
- 這裏的 css 就變相的 阻止了 dom 的解析
- 那麼問題來了,js 會完成 對 div2 的修改嗎?這個時候 的 dom 還沒有執行到 div2,js 自然是 讀取不到 div2 的
- 如果遇到 js 的外鏈呢?
- 這個問題就實在是 老生常談了
- 還要分情況來討論,如 defer (告訴瀏覽器我完全不會操作 dom,所以會 加載文件之後,等到 DOMContentLoaded 之前 順序執行)和 async (加載的時候 不會阻斷 dom,但是 加載完成之後立即執行,這裏就有可能會 阻斷 dom 解析,而且 多個 async 也不是 順序執行的) 的情況
- 然後 就是 將 dom 樹 和 cssom 樹合併,對 靠近視口的 內容 擁有較高的優先級,進行光柵化,呈現到 用戶面前
3、渲染進程——渲染
這裏主要討論一下 js 動畫 和 css 動畫
- 相信有很多人 知道 css 動畫是比 js 動畫 要快的,那麼到底 爲什麼快呢?
- 這裏有很多理由,比如 js 和 dom 樹之間線程的 通信,js 動畫導致的 迴流與重繪
- 講 css 動畫,要了解一個概念,那就是圖層 layers
- 在瀏覽器 的一張 圖片中,頁面 其實是可以進行分層的
- 而進行了 分層的 圖層 就擺脫了 全局的 迴流與重繪的過程,只會 顧着自己的一畝三分地。在內容改變之後,只會 和之前的圖片 一重疊,新的 頁面就這樣 出來了
- 其次,在 js 和 渲染線程之外,瀏覽器 又開了 一個新的 線程,那就是合成 線程,在這個線程上專門用來跑 css 動畫
- 所以有的時候你會發現,當你的 頁面卡住了,css 動畫依舊能夠執行下去
4、看一下 圖層
下面就是百度 原本的 圖層,結構還是很簡單的
找到那個 bottom_layer ,可以看到 是那個 position: fixed 導致了 圖層,我們可以手動的把這個 fixed 改成 absolute
可以發現,以前 箭頭 指着的 bottom_layer 圖層 就這樣消失了
- 很多 css 屬性 都是可以導致 圖層的出現的,比如 transform,will-change 等
- 而且 在這個的基礎上,translate3d 和 will-change 還會啓動 GPU 繪製圖層
- 這樣的話,繪製的 效率自然是大大提升,比 js 動畫 要強了
- 但是要注意的是,額外圖層 的繪製 會導致 內存的 消耗,就像之前有文章 講過的 字節碼 和機器碼 一樣
- 所以 使用 圖層 的方式繪製 要講究 適當,不要什麼都來一波 css 技術紅利
- 可能會有人說 BFC 和圖層之間 又是什麼關係呢?
- position: fixed 是屬於 BFC 的,但是又 屬於 layers,但是 可以看到 position: absolute 是屬於 BFC 的,但是 又不屬於 layers ,所以 要具體情況具體分析了
- (不過根據我的試驗,發現 好像也就 一個 fixed 會創建圖層 ,有興趣的 同學 也可以試試,並且指出我的 錯誤)