從 URL 到頁面展現發生了什么

《從 URL 到頁面展現發生了什么》這是一個老生常談的博客題目

老生常談,在編程界里可以理解為【很重要】

以為個人的理解,前端工程師,說到底就是在研究并實現《從 URL 到頁面展現發生了什么》

我實在能力有限,對于這個題目一直不敢寫,因為這涉及的知識點太廣了

然而再難也得邁出這一步,因為你不寫出來,你永遠不知道自己的水平到底是多有限

今天是入職的前一天晚上,希望在工作的半年或一年以后,我能對這個題目有更加深刻的認識

舉個例子簡短回答

為了更好的理解,我們走一遍流程

  1. 訪問百度主頁
  2. 這個時候 Client 就是瀏覽器,它發了一個請求
  3. 這個請求是發給百度服務器的,也就是上圖的 Server,但是這個說法不太準確,Server 不一定是一個機器,也可能是一個軟件(應用程序)
  4. 接著這個 Server 會返回 Client 一個網頁
  5. 我們就看到了百度

其實以上的例子總結下來就是以下四步么

  • 用戶請求遠程資源
  • 瀏覽器查找遠程資源,打包用戶請求并發送
  • 服務器根據用戶請求的資源路徑及附帶參數,配合自身邏輯生成相關內容,發送給瀏覽器
  • 瀏覽器解析結果,翻譯為直觀方式呈現

好了,回答完畢

標準答案

那么以上步驟具體可以細化為

  1. 輸入地址
  2. 瀏覽器查找域名的 IP 地址
  3. 瀏覽器向 web 服務器發送一個 HTTP 請求
  4. 服務器的永久重定向響應
  5. 瀏覽器跟蹤重定向地址
  6. 服務器處理請求
  7. 服務器返回一個 HTTP 響應
  8. 瀏覽器顯示 HTML
  9. 瀏覽器發送請求獲取嵌入在 HTML 中的資源(如圖片、音頻、視頻、CSS、JS等等)

好了,你對這一系列過程有一個大體的概念了,接下來細說每一個步驟

輸入地址

當我們開始在瀏覽器中輸入網址的時候,瀏覽器其實就已經在智能的匹配可能得 url 了,他會從歷史記錄,書簽等地方,找到已經輸入的字符串可能對應的 url,然后給出智能提示,讓你可以補全url地址。對于 google 的 chrome 的瀏覽器,他甚至會直接從緩存中把網頁展示出來,就是說,你還沒有按下 enter,頁面就出來了。

厲害了

瀏覽器查找域名的 IP 地址

URL 到服務器逐級

  • 一個頁面訪問的本質是我們希望通過一個路徑找到相應的資源
  • 路徑就是我們的 URL,資源是服務器給我們的請求的響應
  • 首先我們需要找到網絡上的服務器才能找到機器上的資源,網絡主機的定位靠的是 IP 地址

域名到IP

IP(Internet Protocol)
: 互聯網中設備間進行通信都要遵從的一種協議,它規定了每臺設備都要有且唯一的 IP 地址,用來標識自己在互聯網中的地址。格式通常為 http://XXX.XXX.XXX.XXX,不同網段下 IP 地址的范圍也不同。如有興趣者,請自行百度。

域名(Domain Name)
: 由于IP協議規定的純數字 IP 地址在日常中難以記憶,因此人們便產生使用更加常見,好記的字符標識設備的地址,域名應運而生。一個域名就是一個更加容易記憶的目標主機的地址標識符。例如:百度的域名就為百度一下,你就知道,實際對應的IP地址為 119.75.217.109

DNS(Domain Name System)
: 互聯網中實際定位設備時還是使用 IP 地址來定位,因此產生了 DNS,一種專門用來將域名轉換為 IP 地址的協議,提供該協議服務的服務器就叫 DNS 服務器。

總結一下

  • 為什么用域名不用IP
    • 因為 IP 有點反人類的記憶思維
  • 域名和 IP 對應 DNS (Domain Name System)

實際上DNS就是一組鍵值對,鍵名就是域名,值就是IP地址

DNS解析

輸入了一個域名,你得靠 DNS 解析出一個相應的 IP 地址吧

  • 瀏覽器緩存:如果之前訪問過該主機,(不是URL指定的資源),瀏覽器會緩存DNS一段時間,這樣就可以直接使用瀏覽器緩存的DNS,至于一段時間是多久沒要求,瀏覽器自行決定
  • 系統緩存:如果瀏覽器緩存里沒有記錄,瀏覽器會做系統調用,獲取系統中的緩存記錄
  • 路由器緩存:如果系統緩存同樣沒有命中,那就需要查詢路由器緩存了
  • ISP(互聯網服務提供商,例如電信,移動)的 DNS 緩存:路由器緩存未命中會查詢 ISP(Internet Service Provider),一般域名在這里都可以找到了
  • 遞歸搜索:我們使用的 ISP 的 DNS 記錄里面如果還沒有的話,那么就會從頂級域名服務器的根域名服務器開始遞歸查詢,這個肯定會查到了

第三者

實際上瀏覽器充當了我們要找到的 IP 地址的第三者,類似中介

可以用以下代碼來看瀏覽器的版本

window.navigator.userAgent
// "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"

瀏覽器向 web 服務器發送一個 HTTP 請求

打包 HTTP 請求

圖中的請求是什么,僅僅是輸入的 URL 么

當然不是,請求是一段報文,包括但不僅僅是 URL

那么請求(request)包含什么呢

  • 請求行
  • 請求頭
  • 空行
  • 消息體

請求又分為兩類

  • GET 請求
  • POST 請求

GET 請求

GET / HTTP/1.1 // 請求行,下面一直到空行之上都是請求頭
Host: www.baidu.com
Accept: text/html
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4
Cookie: BAIDUID=5A056AFFCD3D7072D17933F3750CAB0B:FG=1;
// 空行
// 如果是 GET,那么一般消息體是空的

POST 請求

POST /login/email HTTP/1.1 // 請求行,下面一直到空行之上都是請求頭
Host: www.zhihu.com
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8 // 描述消息體
Content-Length: 119
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9
Cookie: _xsrf=e0f0996099f0c4e3e0157d92d65dfe23;
// 空行
password=zhihu&captcha=mrah&remember_me=true&email=huayiqishi%40qq.com // 消息體

創建 TCP 連接

  • 一般瀏覽器都是通過使用的 TCP 協議,UDP 不可靠,所以瀏覽器得到的 response 要么是全的,要么得不到
  • 瀏覽器打包請求自然也是打包的 HTTP 報文
  • 那么為什么有時候我們看到的頁面是殘缺不全的呢(因為是資源下載失敗了而不是 response 這個文本有殘缺)

瀏覽器發送請求的方法

  • get
  • head
  • post
  • trace
  • options
  • put(往服務器上面放置一些東西)
  • delete(往服務器上刪除一些東西)

一般的瀏覽器只能發起 GET 或者 POST 請求

服務器的永久重定向響應

服務器給瀏覽器響應一個301永久重定向響應,這樣瀏覽器就會訪問 http://www.google.com/ 而非 http://google.com/

為什么服務器一定要重定向而不是直接發送用戶想看的網頁內容呢?其中一個原因跟搜索引擎排名有關。如果一個頁面有兩個地址,就像 http://www.yy.com/http://yy.com/,搜索引擎會認為它們是兩個網站,結果造成每個搜索鏈接都減少從而降低排名。而搜索引擎知道301永久重定向是什么意思,這樣就會把訪問帶 www 的和不帶 www 的地址歸到同一個網站排名下。還有就是用不同的地址會造成緩存友好性變差,當一個頁面有好幾個名字時,它可能會在緩存里出現好幾次。

301和302的區別

301和302狀態碼都表示重定向,就是說瀏覽器在拿到服務器返回的這個狀態碼后會自動跳轉到一個新的 URL 地址,這個地址可以從響應的 Location 首部中獲取(用戶看到的效果就是他輸入的地址 A 瞬間變成了另一個地址 B)——這是它們的共同點。

他們的不同在于

  • 301表示舊地址 A 的資源已經被永久地移除了(這個資源不可訪問了),搜索引擎在抓取新內容的同時也將舊的網址交換為重定向之后的網址;
  • 302表示舊地址 A 的資源還在(仍然可以訪問),這個重定向只是臨時地從舊地址 A 跳轉到地址 B,搜索引擎會抓取新的內容而保存舊的網址。 SEO 302好于301

重定向原因

  • 網站調整(如改變網頁目錄結構)
  • 網頁被移到一個新地址
  • 網頁擴展名改變(如應用需要把.php改成.Html或.shtml)

這種情況下,如果不做重定向,則用戶收藏夾或搜索引擎數據庫中舊地址只能讓訪問客戶得到一個404頁面錯誤信息,訪問流量白白喪失;再者某些注冊了多個域名的網站,也需要通過重定向讓訪問這些域名的用戶自動跳轉到主站點等。

什么時候進行301或者302跳轉

當一個網站或者網頁24—48小時內臨時移動到一個新的位置,這時候就要進行302跳轉,而使用301跳轉的場景就是之前的網站因為某種原因需要移除掉,然后要到新的地址訪問,是永久性的。

清晰明確而言,使用301跳轉的大概場景如下:

  • 域名到期不想續費(或者發現了更適合網站的域名),想換個域名。
  • 在搜索引擎的搜索結果中出現了不帶www的域名,而帶www的域名卻沒有收錄,這個時候可以用301重定向來告訴搜索引擎我們目標的域名是哪一個。
  • 空間服務器不穩定,換空間的時候。

瀏覽器跟蹤重定向地址

現在瀏覽器知道了 "http://www.google.com/"才是要訪問的正確地址,所以它會發送另一個http請求。這里沒有啥好說的

服務器處理請求

相關進程處理請求

主機運行多個程序,那個來處理HTTP請求呢

  • http: 80
  • https: 443
  • ftp: 21
  • ssh: 22

服務器

  • 物理主機
  • web server

服務器返回一個 HTTP 響應

服務器響應請求

哪些內容影響服務器結果呢

  • 請求方法
  • 路徑
  • query string
  • cookkie
  • 服務器配置
  • 動態語言代碼邏輯

服務器響應內容

  • 狀態行
  • 響應頭
  • 響應正文

1. 狀態行

  • 協議版本:是用http1.0還是其他版本
  • 狀態描述:狀態描述給出了關于狀態代碼的簡短的文字描述。比如狀態代碼為200時的描述為 ok
  • 狀態代碼:狀態代碼由三位數字組成,第一個數字定義了響應的類別,且有五種可能取值

例如:HTTP/1.1 200 OK

2. 響應頭

響應頭部:由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號":"分隔,典型的響應頭有:

3. 響應正文

包含著我們需要的一些具體信息,比如cookie,html,image,后端返回的請求數據等等。這里需要注意,響應正文和響應頭之間有一行空格,表示響應頭的信息到空格為止,下圖是fiddler抓到的請求正文,紅色框中的響應正文:

瀏覽器顯示 HTML

渲染頁面

  • 瀏覽器下載的順序是從上到下,渲染的順序也是從上到下,下載和渲染同時進行
  • 解析 HTML 生成 DOM 樹
  • 解析 HTML 中的 CSS,生成渲染樹
  • 解析 JavaScript,解析到的時候執行

瀏覽器是如何把頁面呈現在屏幕上的呢?不同瀏覽器可能解析的過程不太一樣,這里我們只介紹webkit的渲染過程,下圖對應的就是WebKit渲染的過程,這個過程包括:

解析html以構建dom樹 -> 構建render樹 -> 布局render樹 -> 繪制render樹

瀏覽器在解析html文件時,會”自上而下“加載,并在加載過程中進行解析渲染。在解析過程中,如果遇到請求外部資源時,如圖片、外鏈的 CSS、iconfont 等,請求過程是異步的,并不會影響 html 文檔進行加載。

解析過程中,瀏覽器首先會解析 HTML 文件構建 DOM 樹,然后解析 CSS 文件構建渲染樹,等到渲染樹構建完成后,瀏覽器開始布局渲染樹并將其繪制到屏幕上。這個過程比較復雜,涉及到兩個概念: reflow(回流)和 repain(重繪)。

DOM 節點中的各個元素都是以盒模型的形式存在,這些都需要瀏覽器去計算其位置和大小等,這個過程稱為 relow,當盒模型的位置,大小以及其他屬性,如顏色、字體等確定下來之后,瀏覽器便開始繪制內容,這個過程稱為 repain。

頁面在首次加載時必然會經歷 reflow 和 repain。reflow 和 repain 過程是非常消耗性能的,尤其是在移動設備上,它會破壞用戶體驗,有時會造成頁面卡頓。所以我們應該盡可能少的減少 reflow 和 repain。

關聯資源處理

  • 在展現到頁面的某一部分時,即上面的所有部分都已經下載完成
  • 并不是說所有相關聯的元素都已經下載完,圖片,視頻等元素需要另外并行下載
  • 同一個域名下并行下載數量有限制

JS 和 AJAX

  • JS 不能并行的下載和解析,采用阻塞的方式,當頁面引用了 JS 的時候瀏覽器發送請求后會一直阻塞直到得到響應
  • 因為瀏覽器需要1個穩定的 DOM 樹結構,而 JS 中很有可能有代碼直接改變了 DOM 樹結構,瀏覽器為了防止出現 JS 修改 DOM 樹,需要重新構建 DOM 樹的情況,所以就會阻塞其他的下載和呈現
  • 遇到 AJAX 后執行,然后進行下面的步驟,AJAX 拿到結果后再執行 AJAX 回調函數

CSS

  • 樣式表在下載完成后,將和以前下載的所有樣式表一起進行解析,解析完成后,將對此前所有元素(含以前已經渲染的)重新進行渲染
  • JS,CSS 中如果有重定義,后定義將覆蓋之前的定義,而不會報錯

直接使用本地緩存

  • 服務器發給瀏覽器的文件中會帶有 Expires 或 Cache-Control 說明文件什么時候失效
  • 在有效期內的話瀏覽器直接使用本地文件,不發請求

服務器驗證

  • 服務器響應中會帶有文件的最后修改時間或 Etag
  • 瀏覽器發送重復請求會帶上這些信息,如果服務器判斷沒有變化,發送304狀態碼,讓瀏覽器使用本地緩存

好了,從 URL 到頁面展現大概就是這個樣子的

當然了,作為勵志做一名號前端的我們,知道這些是遠遠不夠的,請把以上的每一個點都細化成博客,我相信功力會大增的

學點單詞

  • preserve
    英 [pr??z?:v] 美 [pr??z?rv]
    vt. 保護; 保持,保存; 腌制食物; 防腐處理;
    vi. 保鮮; 保持原狀; 做蜜餞; 禁獵;
    n. 蜜餞; 防護用品; 禁獵地; 獨占的事物(或范圍);
  • cache
    英 [k??] 美 [k??]
    n. 藏物處; 隱藏處; 藏匿的珍寶; <電腦>快速緩沖貯存區;
    vt. 貯藏;
    vi. 躲藏;

參考文章

(完)


文檔信息

  • 自由轉載-非商用-非衍生-保持署名
  • 發表日期:2017年6月4日
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容