記一次完整的http請求

一年即將結束,各位攻城獅們各自打着自己的小算盤,計劃的幹完今年來一波華麗的跳槽,於是一個前端技術交流羣裏有些初入職場的小仙肉們問道關於這些問題,說實際工作中很少關注這些,於是個人準備記錄一下自己的理解

當你在瀏覽器輸入 www.baidu.com 敲下回車,將會發生以下事情:

域名解析 ===> TCP經典的三次握手 ===> 客戶端和服務端建立連接 ===> 發起http/https請求 ===>  漫長的等待(等待服務器響應返回HTML)  ===> 瀏覽器進行 html 解析 ===> 呈現用戶所看到的界面

其實面試官問道這裏,希望你簡單的講述一下整個過程,接下來瀏覽器進行html解析纔是我們前端工程師的重頭戲,這裏主要正對整個解析過程進行詳細解釋:

瀏覽器對html解析通過頁面的渲染引擎和js腳本解析引擎的協同工作來達到呈現頁面的效果

主要包括:HTML解析器、CSS解析器、Layout佈局計算模塊、Render 圖層繪製模塊、Javascript 引擎模塊

  1. HTML解析器: 通過html標籤分析構建 DOM 樹
  2. CSS解析器:通過解析 css 文檔生成 CCSOM 樹
  3. Layout: 計算元素的大小和精確元素的位置
  4. Render :對節點進行像素繪製,將頁面呈現給用戶
  5. Javascript 引擎:對JS腳本進行編譯執行

整個過程通過圖解如下:

當然,作爲一個面試官肯定不希望你就此結束,既然知道了渲染流程,我們作爲面試者是不是應該懂得更多一點,站在開發的角度上來講,我們應該瞭解需求你說呢,順便聊一聊基於流程化的優化:

從CSS開始,我們都知道樣式選擇器有很多,從 *、id、class、僞類、子代、後代……等等,可實際開發中我們讓我們鍾情也就那麼幾個,除了 id 就是 class,其它的全部只讓TA停留在記憶裏,效率不高且用法繁瑣,作爲面試官,我從來都不問求職者諸如有哪些選擇器之類有失面試官水平的話,只會求職者談一談如何優化。

CSS選擇器使用

  • 避免通用匹配,目標明確,只對需要用到的元素進行選擇
  • 儘可能的使用可繼承的屬性:eg: fontSize、fongFamily 等
  • 少用標籤選擇器
  • 避免多個選擇器的結合使用 eg: .list#title (完全沒必要,一個可以搞定的不要用兩個)
  • 減少選擇器的嵌套(沒有最好,好的 html 結構和頁面佈局,一個 class 完全可以搞定一切)

說完css選擇器的使用,再順待聊聊加載順序,爲啥雅虎鐵規 css top , javascript bottom

CSS 與 JS 的加載優化

css 阻塞

在一開始的瀏覽器解析 HTML 的過程中我們就知道, DOM 和 CSSOM 結合才能夠完美的呈現給用戶界面,默認情況下,css 是會阻塞 DOM 的顯示的,瀏覽器不想頁面“裸奔”啊,光禿禿的頁面體驗肯定查到了極點。如今的小盆友的不傳開襠褲,更何況瀏覽器背後那些開發大佬們,你說對吧。

如此,我們就需要儘可能早的將TA下載到客戶端,以便縮短頁面的渲染時間,於是也就有了CSS top,萬事皆有因果,所以這也不是空穴來風。

js阻塞

囉嗦了半天,都沒有提到 JS ,各位看官是不是有點不耐煩了,壓軸戲一般都放在後頭,心急之人怎麼可以吃到熱豆腐。感謝自己讀到了這裏哈……

直接上🌰

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>JS阻塞測試</title>
  <style>
    #container {
      background-color: yellow;
      width: 100px;
      height: 100px;
    }
  </style>
  <script>
    // 嘗試獲取container元素
    var container = document.getElementById("container")
    console.log('container', container)
  </script>
</head>
<body>
  <div id="container"></div>
  <script>
    // 嘗試獲取container元素
    var container = document.getElementById("container")
    console.log('container', container)
    // 輸出container元素此刻的背景色
    console.log('container bgColor', getComputedStyle(container).backgroundColor)
  </script>
  <style>
    #container {
      background-color: blue;
    }
  </style>
</body>
</html>

上數demo的結果爲:

" container" null

" container " " <div id = 'containre'></div> "

" container bgColor"  "rgb(255, 255, 0)"

我們在分析一下原因:

第一條 console.log 結果以鐵證向我們證明了頁面元素還沒有生成

第二條 console.log 結果因爲實在元素之後,和我們想要的一樣,沒毛病

第三條 console.log 結果是 yellow 的顏色,因爲 後面的 <style></style>並沒有執行
結合以上山條結果,不難得出 JS 阻塞頁面的渲染

但是爲什麼呢?這裏我們就不得不說回到最初的瀏覽器渲染引擎了,我們都知道,JS 引擎是獨立於 渲染 引擎而存在的,而且兩種引擎的優先級是 JS 引擎要高,因爲我們的 JS 是用來對界面進項交互操作,渲染引擎不知道 JS 引擎具體要幹嘛,是否會導致重繪和佈局,所以乾脆等到 js 執行完成後再進行渲染,否則的話就會出現混亂。正式處於這種原因,所以纔會有 JS 阻塞頁面加載的痛點了,既然知道了問題所在,那就需要解決了

JS 的三種加載方式:

<script type=text/javascript src=a.js></script> // 正常加載

<script type=text/javascript defer src=a.js></script> // 延遲加載

<script type=text/javascript async src=a.js></script> // 異步加載

 

如果你的 JS 對頁面有操作,務必延遲加載,否則異步加載就好,正常加載遵循 JS bottom 就好了

 

前端性能優化 css 和 js  片就到這裏,後續會持續寫 http 緩存 、 客戶端緩存以及服務器端緩存,這都是前端優化的點,希望和大家一起堅持學習

 

其它階段請參考文章 https://blog.csdn.net/u014600626/article/details/78720763 (深度好文章)

 

 

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