從 URL 到頁(yè)面展現(xiàn)發(fā)生了什么

《從 URL 到頁(yè)面展現(xiàn)發(fā)生了什么》這是一個(gè)老生常談的博客題目

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

以為個(gè)人的理解,前端工程師,說到底就是在研究并實(shí)現(xiàn)《從 URL 到頁(yè)面展現(xiàn)發(fā)生了什么》

我實(shí)在能力有限,對(duì)于這個(gè)題目一直不敢寫,因?yàn)檫@涉及的知識(shí)點(diǎn)太廣了

然而再難也得邁出這一步,因?yàn)槟悴粚懗鰜恚阌肋h(yuǎn)不知道自己的水平到底是多有限

今天是入職的前一天晚上,希望在工作的半年或一年以后,我能對(duì)這個(gè)題目有更加深刻的認(rèn)識(shí)

舉個(gè)例子簡(jiǎn)短回答

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

  1. 訪問百度主頁(yè)
  2. 這個(gè)時(shí)候 Client 就是瀏覽器,它發(fā)了一個(gè)請(qǐng)求
  3. 這個(gè)請(qǐng)求是發(fā)給百度服務(wù)器的,也就是上圖的 Server,但是這個(gè)說法不太準(zhǔn)確,Server 不一定是一個(gè)機(jī)器,也可能是一個(gè)軟件(應(yīng)用程序)
  4. 接著這個(gè) Server 會(huì)返回 Client 一個(gè)網(wǎng)頁(yè)
  5. 我們就看到了百度

其實(shí)以上的例子總結(jié)下來就是以下四步么

  • 用戶請(qǐng)求遠(yuǎn)程資源
  • 瀏覽器查找遠(yuǎn)程資源,打包用戶請(qǐng)求并發(fā)送
  • 服務(wù)器根據(jù)用戶請(qǐng)求的資源路徑及附帶參數(shù),配合自身邏輯生成相關(guān)內(nèi)容,發(fā)送給瀏覽器
  • 瀏覽器解析結(jié)果,翻譯為直觀方式呈現(xiàn)

好了,回答完畢

標(biāo)準(zhǔn)答案

那么以上步驟具體可以細(xì)化為

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

好了,你對(duì)這一系列過程有一個(gè)大體的概念了,接下來細(xì)說每一個(gè)步驟

輸入地址

當(dāng)我們開始在瀏覽器中輸入網(wǎng)址的時(shí)候,瀏覽器其實(shí)就已經(jīng)在智能的匹配可能得 url 了,他會(huì)從歷史記錄,書簽等地方,找到已經(jīng)輸入的字符串可能對(duì)應(yīng)的 url,然后給出智能提示,讓你可以補(bǔ)全url地址。對(duì)于 google 的 chrome 的瀏覽器,他甚至?xí)苯訌木彺嬷邪丫W(wǎng)頁(yè)展示出來,就是說,你還沒有按下 enter,頁(yè)面就出來了。

厲害了

瀏覽器查找域名的 IP 地址

URL 到服務(wù)器逐級(jí)

  • 一個(gè)頁(yè)面訪問的本質(zhì)是我們希望通過一個(gè)路徑找到相應(yīng)的資源
  • 路徑就是我們的 URL,資源是服務(wù)器給我們的請(qǐng)求的響應(yīng)
  • 首先我們需要找到網(wǎng)絡(luò)上的服務(wù)器才能找到機(jī)器上的資源,網(wǎng)絡(luò)主機(jī)的定位靠的是 IP 地址

域名到IP

IP(Internet Protocol)
: 互聯(lián)網(wǎng)中設(shè)備間進(jìn)行通信都要遵從的一種協(xié)議,它規(guī)定了每臺(tái)設(shè)備都要有且唯一的 IP 地址,用來標(biāo)識(shí)自己在互聯(lián)網(wǎng)中的地址。格式通常為 http://XXX.XXX.XXX.XXX,不同網(wǎng)段下 IP 地址的范圍也不同。如有興趣者,請(qǐng)自行百度。

域名(Domain Name)
: 由于IP協(xié)議規(guī)定的純數(shù)字 IP 地址在日常中難以記憶,因此人們便產(chǎn)生使用更加常見,好記的字符標(biāo)識(shí)設(shè)備的地址,域名應(yīng)運(yùn)而生。一個(gè)域名就是一個(gè)更加容易記憶的目標(biāo)主機(jī)的地址標(biāo)識(shí)符。例如:百度的域名就為百度一下,你就知道,實(shí)際對(duì)應(yīng)的IP地址為 119.75.217.109

DNS(Domain Name System)
: 互聯(lián)網(wǎng)中實(shí)際定位設(shè)備時(shí)還是使用 IP 地址來定位,因此產(chǎn)生了 DNS,一種專門用來將域名轉(zhuǎn)換為 IP 地址的協(xié)議,提供該協(xié)議服務(wù)的服務(wù)器就叫 DNS 服務(wù)器。

總結(jié)一下

  • 為什么用域名不用IP
    • 因?yàn)?IP 有點(diǎn)反人類的記憶思維
  • 域名和 IP 對(duì)應(yīng) DNS (Domain Name System)

實(shí)際上DNS就是一組鍵值對(duì),鍵名就是域名,值就是IP地址

DNS解析

輸入了一個(gè)域名,你得靠 DNS 解析出一個(gè)相應(yīng)的 IP 地址吧

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

第三者

實(shí)際上瀏覽器充當(dāng)了我們要找到的 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 服務(wù)器發(fā)送一個(gè) HTTP 請(qǐng)求

打包 HTTP 請(qǐng)求

圖中的請(qǐng)求是什么,僅僅是輸入的 URL 么

當(dāng)然不是,請(qǐng)求是一段報(bào)文,包括但不僅僅是 URL

那么請(qǐng)求(request)包含什么呢

  • 請(qǐng)求行
  • 請(qǐng)求頭
  • 空行
  • 消息體

請(qǐng)求又分為兩類

  • GET 請(qǐng)求
  • POST 請(qǐng)求

GET 請(qǐng)求

GET / HTTP/1.1 // 請(qǐng)求行,下面一直到空行之上都是請(qǐng)求頭
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 請(qǐng)求

POST /login/email HTTP/1.1 // 請(qǐng)求行,下面一直到空行之上都是請(qǐng)求頭
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 // 消息體

創(chuàng)建 TCP 連接

  • 一般瀏覽器都是通過使用的 TCP 協(xié)議,UDP 不可靠,所以瀏覽器得到的 response 要么是全的,要么得不到
  • 瀏覽器打包請(qǐng)求自然也是打包的 HTTP 報(bào)文
  • 那么為什么有時(shí)候我們看到的頁(yè)面是殘缺不全的呢(因?yàn)槭琴Y源下載失敗了而不是 response 這個(gè)文本有殘缺)

瀏覽器發(fā)送請(qǐng)求的方法

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

一般的瀏覽器只能發(fā)起 GET 或者 POST 請(qǐng)求

服務(wù)器的永久重定向響應(yīng)

服務(wù)器給瀏覽器響應(yīng)一個(gè)301永久重定向響應(yīng),這樣瀏覽器就會(huì)訪問 http://www.google.com/ 而非 http://google.com/。

為什么服務(wù)器一定要重定向而不是直接發(fā)送用戶想看的網(wǎng)頁(yè)內(nèi)容呢?其中一個(gè)原因跟搜索引擎排名有關(guān)。如果一個(gè)頁(yè)面有兩個(gè)地址,就像 http://www.yy.com/http://yy.com/,搜索引擎會(huì)認(rèn)為它們是兩個(gè)網(wǎng)站,結(jié)果造成每個(gè)搜索鏈接都減少?gòu)亩档团琶?。而搜索引擎知?01永久重定向是什么意思,這樣就會(huì)把訪問帶 www 的和不帶 www 的地址歸到同一個(gè)網(wǎng)站排名下。還有就是用不同的地址會(huì)造成緩存友好性變差,當(dāng)一個(gè)頁(yè)面有好幾個(gè)名字時(shí),它可能會(huì)在緩存里出現(xiàn)好幾次。

301和302的區(qū)別

301和302狀態(tài)碼都表示重定向,就是說瀏覽器在拿到服務(wù)器返回的這個(gè)狀態(tài)碼后會(huì)自動(dòng)跳轉(zhuǎn)到一個(gè)新的 URL 地址,這個(gè)地址可以從響應(yīng)的 Location 首部中獲?。ㄓ脩艨吹降男Ч褪撬斎氲牡刂?A 瞬間變成了另一個(gè)地址 B)——這是它們的共同點(diǎn)。

他們的不同在于

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

重定向原因

  • 網(wǎng)站調(diào)整(如改變網(wǎng)頁(yè)目錄結(jié)構(gòu))
  • 網(wǎng)頁(yè)被移到一個(gè)新地址
  • 網(wǎng)頁(yè)擴(kuò)展名改變(如應(yīng)用需要把.php改成.Html或.shtml)

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

什么時(shí)候進(jìn)行301或者302跳轉(zhuǎn)

當(dāng)一個(gè)網(wǎng)站或者網(wǎng)頁(yè)24—48小時(shí)內(nèi)臨時(shí)移動(dòng)到一個(gè)新的位置,這時(shí)候就要進(jìn)行302跳轉(zhuǎn),而使用301跳轉(zhuǎn)的場(chǎng)景就是之前的網(wǎng)站因?yàn)槟撤N原因需要移除掉,然后要到新的地址訪問,是永久性的。

清晰明確而言,使用301跳轉(zhuǎn)的大概場(chǎng)景如下:

  • 域名到期不想續(xù)費(fèi)(或者發(fā)現(xiàn)了更適合網(wǎng)站的域名),想換個(gè)域名。
  • 在搜索引擎的搜索結(jié)果中出現(xiàn)了不帶www的域名,而帶www的域名卻沒有收錄,這個(gè)時(shí)候可以用301重定向來告訴搜索引擎我們目標(biāo)的域名是哪一個(gè)。
  • 空間服務(wù)器不穩(wěn)定,換空間的時(shí)候。

瀏覽器跟蹤重定向地址

現(xiàn)在瀏覽器知道了 "http://www.google.com/"才是要訪問的正確地址,所以它會(huì)發(fā)送另一個(gè)http請(qǐng)求。這里沒有啥好說的

服務(wù)器處理請(qǐng)求

相關(guān)進(jìn)程處理請(qǐng)求

主機(jī)運(yùn)行多個(gè)程序,那個(gè)來處理HTTP請(qǐng)求呢

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

服務(wù)器

  • 物理主機(jī)
  • web server

服務(wù)器返回一個(gè) HTTP 響應(yīng)

服務(wù)器響應(yīng)請(qǐng)求

哪些內(nèi)容影響服務(wù)器結(jié)果呢

  • 請(qǐng)求方法
  • 路徑
  • query string
  • cookkie
  • 服務(wù)器配置
  • 動(dòng)態(tài)語(yǔ)言代碼邏輯

服務(wù)器響應(yīng)內(nèi)容

  • 狀態(tài)行
  • 響應(yīng)頭
  • 響應(yīng)正文

1. 狀態(tài)行

  • 協(xié)議版本:是用http1.0還是其他版本
  • 狀態(tài)描述:狀態(tài)描述給出了關(guān)于狀態(tài)代碼的簡(jiǎn)短的文字描述。比如狀態(tài)代碼為200時(shí)的描述為 ok
  • 狀態(tài)代碼:狀態(tài)代碼由三位數(shù)字組成,第一個(gè)數(shù)字定義了響應(yīng)的類別,且有五種可能取值

例如:HTTP/1.1 200 OK

2. 響應(yīng)頭

響應(yīng)頭部:由關(guān)鍵字/值對(duì)組成,每行一對(duì),關(guān)鍵字和值用英文冒號(hào)":"分隔,典型的響應(yīng)頭有:

3. 響應(yīng)正文

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

瀏覽器顯示 HTML

渲染頁(yè)面

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

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

解析html以構(gòu)建dom樹 -> 構(gòu)建render樹 -> 布局render樹 -> 繪制render樹

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

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

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

頁(yè)面在首次加載時(shí)必然會(huì)經(jīng)歷 reflow 和 repain。reflow 和 repain 過程是非常消耗性能的,尤其是在移動(dòng)設(shè)備上,它會(huì)破壞用戶體驗(yàn),有時(shí)會(huì)造成頁(yè)面卡頓。所以我們應(yīng)該盡可能少的減少 reflow 和 repain。

關(guān)聯(lián)資源處理

  • 在展現(xiàn)到頁(yè)面的某一部分時(shí),即上面的所有部分都已經(jīng)下載完成
  • 并不是說所有相關(guān)聯(lián)的元素都已經(jīng)下載完,圖片,視頻等元素需要另外并行下載
  • 同一個(gè)域名下并行下載數(shù)量有限制

JS 和 AJAX

  • JS 不能并行的下載和解析,采用阻塞的方式,當(dāng)頁(yè)面引用了 JS 的時(shí)候?yàn)g覽器發(fā)送請(qǐng)求后會(huì)一直阻塞直到得到響應(yīng)
  • 因?yàn)闉g覽器需要1個(gè)穩(wěn)定的 DOM 樹結(jié)構(gòu),而 JS 中很有可能有代碼直接改變了 DOM 樹結(jié)構(gòu),瀏覽器為了防止出現(xiàn) JS 修改 DOM 樹,需要重新構(gòu)建 DOM 樹的情況,所以就會(huì)阻塞其他的下載和呈現(xiàn)
  • 遇到 AJAX 后執(zhí)行,然后進(jìn)行下面的步驟,AJAX 拿到結(jié)果后再執(zhí)行 AJAX 回調(diào)函數(shù)

CSS

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

直接使用本地緩存

  • 服務(wù)器發(fā)給瀏覽器的文件中會(huì)帶有 Expires 或 Cache-Control 說明文件什么時(shí)候失效
  • 在有效期內(nèi)的話瀏覽器直接使用本地文件,不發(fā)請(qǐng)求

服務(wù)器驗(yàn)證

  • 服務(wù)器響應(yīng)中會(huì)帶有文件的最后修改時(shí)間或 Etag
  • 瀏覽器發(fā)送重復(fù)請(qǐng)求會(huì)帶上這些信息,如果服務(wù)器判斷沒有變化,發(fā)送304狀態(tài)碼,讓瀏覽器使用本地緩存

好了,從 URL 到頁(yè)面展現(xiàn)大概就是這個(gè)樣子的

當(dāng)然了,作為勵(lì)志做一名號(hào)前端的我們,知道這些是遠(yuǎn)遠(yuǎn)不夠的,請(qǐng)把以上的每一個(gè)點(diǎn)都細(xì)化成博客,我相信功力會(huì)大增的

學(xué)點(diǎn)單詞

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

參考文章

(完)


文檔信息

  • 自由轉(zhuǎn)載-非商用-非衍生-保持署名
  • 發(fā)表日期:2017年6月4日
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容