瀏覽器輸入URL后發(fā)生了什么

學(xué)號:17020110019? ? 姓名:高少魁

轉(zhuǎn)載自:https://mp.weixin.qq.com/s/hYvAupzObxnWJa2kV8SsFw

【嵌牛導(dǎo)讀】在瀏覽器中輸入一個合法的URL后走哺,瀏覽器會針對此URL做出一系列的反應(yīng)拭荤,大致流程為:URL解析蛹磺、DNS查詢只厘、TCP連接愉阎、處理請求标捺、接收響應(yīng)氛堕、渲染界面六個流程顾瞪,本文從這六個流程出發(fā)簡單的介紹了瀏覽器對于URL的操作掷邦,本文的步驟是建立在汪诉,請求的是一個簡單的 HTTP 請求废恋,沒有 HTTPS、HTTP2扒寄、最簡單的 DNS鱼鼓、沒有代理、并且服務(wù)器沒有任何問題的基礎(chǔ)上该编,盡管這是不切實際的迄本。

【嵌牛鼻子】URL? ? 瀏覽器? ? 計算機網(wǎng)絡(luò)? ? HTTP? ? TCP

【嵌牛正文】

URL解析

地址解析:

首先判斷你輸入的是一個合法的 URL 還是一個待搜索的關(guān)鍵詞,并且根據(jù)你輸入的內(nèi)容進行自動完成课竣、字符編碼等操作嘉赎。

HSTS

由于安全隱患置媳,會使用 HSTS 強制客戶端使用 HTTPS 訪問頁面。詳見:你所不知道的 HSTS[1]公条。

其他操作

瀏覽器還會進行一些額外的操作拇囊,比如安全檢查、訪問限制(之前國產(chǎn)瀏覽器限制 996.icu)靶橱。

檢查緩存

DNS查詢

基本步驟

1. 瀏覽器緩存

瀏覽器會先檢查是否在緩存中寥袭,沒有則調(diào)用系統(tǒng)庫函數(shù)進行查詢。

2. 操作系統(tǒng)緩存

操作系統(tǒng)也有自己的 DNS緩存抓韩,但在這之前纠永,會向檢查域名是否存在本地的 Hosts 文件里,沒有則向 DNS 服務(wù)器發(fā)送查詢請求谒拴。

3. 路由器緩存

路由器也有自己的緩存尝江。

4. ISP DNS 緩存

ISP DNS 就是在客戶端電腦上設(shè)置的首選 DNS 服務(wù)器,它們在大多數(shù)情況下都會有緩存英上。

根域名服務(wù)器查詢

在前面所有步驟沒有緩存的情況下炭序,本地 DNS 服務(wù)器會將請求轉(zhuǎn)發(fā)到互聯(lián)網(wǎng)上的根域,下面這個圖很好的詮釋了整個流程:

根域名服務(wù)器(維基百科)

需要注意的點

1.遞歸方式:一路查下去中間不返回苍日,得到最終結(jié)果才返回信息(瀏覽器到本地DNS服務(wù)器的過程)

2.迭代方式惭聂,就是本地DNS服務(wù)器到根域名服務(wù)器查詢的方式。

3.什么是 DNS 劫持

4.前端 dns-prefetch 優(yōu)化

TCP連接

TCP/IP 分為四層相恃,在發(fā)送數(shù)據(jù)時辜纲,每層都要對數(shù)據(jù)進行封裝:

1. 應(yīng)用層:發(fā)送 HTTP 請求

在前面的步驟我們已經(jīng)得到服務(wù)器的 IP 地址,瀏覽器會開始構(gòu)造一個 HTTP 報文拦耐,其中包括:

請求報頭(Request Header):請求方法耕腾、目標(biāo)地址、遵循的協(xié)議等等

請求主體(其他參數(shù))

其中需要注意的點:

瀏覽器只能發(fā)送 GET杀糯、POST 方法扫俺,而打開網(wǎng)頁使用的是 GET 方法

2. 傳輸層:TCP 傳輸報文

傳輸層會發(fā)起一條到達服務(wù)器的 TCP 連接,為了方便傳輸固翰,會對數(shù)據(jù)進行分割(以報文段為單位)狼纬,并標(biāo)記編號,方便服務(wù)器接受時能夠準(zhǔn)確地還原報文信息骂际。

在建立連接前疗琉,會先進行 TCP 三次握手。

3. 網(wǎng)絡(luò)層:IP協(xié)議查詢Mac地址

將數(shù)據(jù)段打包歉铝,并加入源及目標(biāo)的IP地址没炒,并且負責(zé)尋找傳輸路線。

判斷目標(biāo)地址是否與當(dāng)前地址處于同一網(wǎng)絡(luò)中,是的話直接根據(jù) Mac 地址發(fā)送送火,否則使用路由表查找下一跳地址拳话,以及使用 ARP 協(xié)議查詢它的 Mac 地址。

“注意:在 OSI 參考模型中 ARP 協(xié)議位于鏈路層种吸,但在 TCP/IP 中弃衍,它位于網(wǎng)絡(luò)層〖崴祝”

4. 鏈路層:以太網(wǎng)協(xié)議

以太網(wǎng)協(xié)議

根據(jù)以太網(wǎng)協(xié)議將數(shù)據(jù)分為以“幀”為單位的數(shù)據(jù)包镜盯,每一幀分為兩個部分:

標(biāo)頭:數(shù)據(jù)包的發(fā)送者、接受者猖败、數(shù)據(jù)類型

數(shù)據(jù):數(shù)據(jù)包具體內(nèi)容

Mac 地址

以太網(wǎng)規(guī)定了連入網(wǎng)絡(luò)的所有設(shè)備都必須具備“網(wǎng)卡”接口速缆,數(shù)據(jù)包都是從一塊網(wǎng)卡傳遞到另一塊網(wǎng)卡,網(wǎng)卡的地址就是 Mac 地址恩闻。每一個 Mac 地址都是獨一無二的艺糜,具備了一對一的能力。

廣播

發(fā)送數(shù)據(jù)的方法很原始幢尚,直接把數(shù)據(jù)通過 ARP 協(xié)議破停,向本網(wǎng)絡(luò)的所有機器發(fā)送,接收方根據(jù)標(biāo)頭信息與自身 Mac 地址比較尉剩,一致就接受真慢,否則丟棄。

服務(wù)器接受請求

接受過程就是把以上步驟逆轉(zhuǎn)過來理茎,參見上圖黑界。

服務(wù)器處理請求

大致流程

HTTPD

最常見的 HTTPD 有 Linux 上常用的 Apache 和 Nginx,以及 Windows 上的 IIS皂林。

它會監(jiān)聽得到的請求朗鸠,然后開啟一個子進程去處理這個請求。

處理請求

接受 TCP 報文后式撼,會對連接進行處理童社,對HTTP協(xié)議進行解析(請求方法求厕、域名著隆、路徑等),并且進行一些驗證:

????驗證是否配置虛擬主機

????驗證虛擬主機是否接受此方法

????驗證該用戶可以使用該方法(根據(jù) IP 地址呀癣、身份信息等)

重定向

假如服務(wù)器配置了 HTTP 重定向美浦,就會返回一個 301永久重定向響應(yīng),瀏覽器就會根據(jù)響應(yīng)项栏,重新發(fā)送 HTTP 請求(重新執(zhí)行上面的過程)

URL 重寫

然后會查看 URL 重寫規(guī)則浦辨,如果請求的文件是真實存在的,比如圖片沼沈、html流酬、css币厕、js文件等,則會直接把這個文件返回芽腾。

否則服務(wù)器會按照規(guī)則把請求重寫到 一個 REST 風(fēng)格的 URL 上旦装。

然后根據(jù)動態(tài)語言的腳本,來決定調(diào)用什么類型的動態(tài)文件解釋器來處理這個請求摊滔。

以 PHP 語言的 MVC 框架舉例阴绢,它首先會初始化一些環(huán)境的參數(shù),根據(jù) URL 由上到下地去匹配路由艰躺,然后讓路由所定義的方法去處理請求呻袭。

瀏覽器接收響應(yīng)

瀏覽器接收到來自服務(wù)器的響應(yīng)資源后,會對資源進行分析腺兴。

首先查看 Response header左电,根據(jù)不同狀態(tài)碼做不同的事(比如上面提到的重定向)。

如果響應(yīng)資源進行了壓縮(比如 gzip)含长,還需要進行解壓券腔。

然后,對響應(yīng)資源做緩存拘泞。

接下來纷纫,根據(jù)響應(yīng)資源里的 MIME[3]?類型去解析響應(yīng)內(nèi)容(比如 HTML、Image各有不同的解析方式)陪腌。

渲染頁面

不同的瀏覽器內(nèi)核辱魁,渲染過程也不完全相同,但大致流程都差不多诗鸭。

基本流程

6.1. HTML 解析

首先要知道瀏覽器解析是從上往下一行一行地解析的染簇。

解析的過程可以分為四個步驟:

① 解碼(encoding)

傳輸回來的其實都是一些二進制字節(jié)數(shù)據(jù),瀏覽器需要根據(jù)文件指定編碼(例如UTF-8)轉(zhuǎn)換成字符串强岸,也就是HTML 代碼锻弓。

② 預(yù)解析(pre-parsing)

預(yù)解析做的事情是提前加載資源,減少處理時間蝌箍,它會識別一些會請求資源的屬性青灼,比如img標(biāo)簽的src屬性,并將這個請求加到請求隊列中妓盲。

③ 符號化(Tokenization)

符號化是詞法分析的過程杂拨,將輸入解析成符號,HTML 符號包括悯衬,開始標(biāo)簽弹沽、結(jié)束標(biāo)簽、屬性名和屬性值。

它通過一個狀態(tài)機去識別符號的狀態(tài)策橘,比如遇到<炸渡,>狀態(tài)都會產(chǎn)生變化。

④ 構(gòu)建樹(tree construction)

“注意:符號化和構(gòu)建樹是并行操作的丽已,也就是說只要解析到一個開始標(biāo)簽偶摔,就會創(chuàng)建一個 DOM 節(jié)點〈俾觯”

在上一步符號化中辰斋,解析器獲得這些標(biāo)記,然后以合適的方法創(chuàng)建DOM對象并把這些符號插入到DOM對象中瘸味。

瀏覽器容錯進制

你從來沒有在瀏覽器看過類似”語法無效”的錯誤宫仗,這是因為瀏覽器去糾正錯誤的語法,然后繼續(xù)工作旁仿。

事件

當(dāng)整個解析的過程完成以后藕夫,瀏覽器會通過DOMContentLoaded事件來通知DOM解析完成。

6.2. CSS 解析

一旦瀏覽器下載了 CSS枯冈,CSS 解析器就會處理它遇到的任何 CSS毅贮,根據(jù)語法規(guī)范[4]解析出所有的 CSS 并進行標(biāo)記化,然后我們得到一個規(guī)則表尘奏。

CSS 匹配規(guī)則

在匹配一個節(jié)點對應(yīng)的 CSS 規(guī)則時滩褥,是按照從右到左的順序的,例如:div p { font-size :14px }會先尋找所有的p標(biāo)簽然后判斷它的父元素是否為div炫加。

所以我們寫 CSS 時瑰煎,盡量用 id 和 class,千萬不要過度層疊俗孝。

6.3. 渲染樹

其實這就是一個 DOM 樹和 CSS 規(guī)則樹合并的過程酒甸。

“注意:渲染樹會忽略那些不需要渲染的節(jié)點,比如設(shè)置了display:none的節(jié)點赋铝〔迩冢”

計算

通過計算讓任何尺寸值都減少到三個可能之一:auto、百分比革骨、px农尖,比如把rem轉(zhuǎn)化為px。

級聯(lián)

瀏覽器需要一種方法來確定哪些樣式才真正需要應(yīng)用到對應(yīng)元素苛蒲,所以它使用一個叫做specificity的公式卤橄,這個公式會通過:

標(biāo)簽名绿满、class臂外、id

是否內(nèi)聯(lián)樣式

!important

然后得出一個權(quán)重值,取最高的那個。

渲染阻塞

當(dāng)遇到一個script標(biāo)簽時漏健,DOM 構(gòu)建會被暫停嚎货,直至腳本完成執(zhí)行,然后繼續(xù)構(gòu)建 DOM 樹蔫浆。

但如果 JS 依賴 CSS 樣式殖属,而它還沒有被下載和構(gòu)建時,瀏覽器就會延遲腳本執(zhí)行瓦盛,直至 CSS Rules 被構(gòu)建洗显。

所有我們知道:

CSS 會阻塞 JS 執(zhí)行

JS 會阻塞后面的 DOM 解析

為了避免這種情況,應(yīng)該以下原則:

CSS 資源排在 JavaScript 資源前面

JS 放在 HTML 最底部原环,也就是?</body>前

另外挠唆,如果要改變阻塞模式,可以使用 defer 與 async

6.4. 布局與繪制

確定渲染樹種所有節(jié)點的幾何屬性嘱吗,比如:位置玄组、大小等等,最后輸入一個盒子模型谒麦,它能精準(zhǔn)地捕獲到每個元素在屏幕內(nèi)的準(zhǔn)確位置與大小俄讹。

然后遍歷渲染樹,調(diào)用渲染器的 paint() 方法在屏幕上顯示其內(nèi)容绕德。

6.5. 合并渲染層

把以上繪制的所有圖片合并患膛,最終輸出一張圖片。

6.6. 回流與重繪

回流(reflow)

當(dāng)瀏覽器發(fā)現(xiàn)某個部分發(fā)現(xiàn)變化影響了布局時耻蛇,需要倒回去重新渲染剩瓶,會從html標(biāo)簽開始遞歸往下,重新計算位置和大小城丧。

reflow基本是無法避免的延曙,因為當(dāng)你滑動一下鼠標(biāo)、resize 窗口亡哄,頁面就會產(chǎn)生變化枝缔。

重繪(repaint)

改變了某個元素的背景色、文字顏色等等不會影響周圍元素的位置變化時蚊惯,就會發(fā)生重繪愿卸。

每次重繪后,瀏覽器還需要合并渲染層并輸出到屏幕上截型。

回流的成本要比重繪高很多趴荸,所以我們應(yīng)該盡量避免產(chǎn)生回流。

比如:

display:none 會觸發(fā)回流宦焦,而 visibility:hidden 只會觸發(fā)重繪发钝。

6.7. JavaScript 編譯執(zhí)行

大致流程

可以分為三個階段:

1. 詞法分析

JS 腳本加載完畢后顿涣,會首先進入語法分析階段,它首先會分析代碼塊的語法是否正確酝豪,不正確則拋出“語法錯誤”涛碑,停止執(zhí)行。

幾個步驟:

分詞孵淘,例如將var a = 2蒲障,,分成var瘫证、a揉阎、=、2這樣的詞法單元背捌。

解析余黎,將詞法單元轉(zhuǎn)換成抽象語法樹(AST)。

代碼生成载萌,將抽象語法樹轉(zhuǎn)換成機器指令惧财。

2. 預(yù)編譯

JS 有三種運行環(huán)境:

全局環(huán)境

函數(shù)環(huán)境

eval

每進入一個不同的運行環(huán)境都會創(chuàng)建一個對應(yīng)的執(zhí)行上下文,根據(jù)不同的上下文環(huán)境扭仁,形成一個函數(shù)調(diào)用棧垮衷,棧底永遠是全局執(zhí)行上下文,棧頂則永遠是當(dāng)前執(zhí)行上下文乖坠。

創(chuàng)建執(zhí)行上下文

創(chuàng)建執(zhí)行上下文的過程中搀突,主要做了以下三件事:

創(chuàng)建變量對象

參數(shù)、函數(shù)熊泵、變量

建立作用域鏈

確認(rèn)當(dāng)前執(zhí)行環(huán)境是否能訪問變量

確定 This 指向

3. 執(zhí)行

JS 線程

雖然 JS 是單線程的仰迁,但實際上參與工作的線程一共有四個:

“其中三個只是協(xié)助,只有 JS 引擎線程是真正執(zhí)行的”

JS 引擎線程:也叫 JS 內(nèi)核顽分,負責(zé)解析執(zhí)行 JS 腳本程序的主線程徐许,例如 V8 引擎

事件觸發(fā)線程:屬于瀏覽器內(nèi)核線程,主要用于控制事件卒蘸,例如鼠標(biāo)雌隅、鍵盤等,當(dāng)事件被觸發(fā)時缸沃,就會把事件的處理函數(shù)推進事件隊列恰起,等待 JS 引擎線程執(zhí)行

定時器觸發(fā)線程:主要控制setInterval和setTimeout,用來計時趾牧,計時完畢后检盼,則把定時器的處理函數(shù)推進事件隊列中,等待 JS 引擎線程翘单。

HTTP 異步請求線程:通過XMLHttpRequest連接后吨枉,通過瀏覽器新開的一個線程蹦渣,監(jiān)控readyState狀態(tài)變更時,如果設(shè)置了該狀態(tài)的回調(diào)函數(shù)东羹,則將該狀態(tài)的處理函數(shù)推進事件隊列中,等待JS引擎線程執(zhí)行忠烛。

宏任務(wù)分為:

同步任務(wù):按照順序執(zhí)行属提,只有前一個任務(wù)完成后,才能執(zhí)行后一個任務(wù)

異步任務(wù):不直接執(zhí)行美尸,只有滿足觸發(fā)條件時冤议,相關(guān)的線程將該異步任務(wù)推進任務(wù)隊列中,等待JS引擎主線程上的任務(wù)執(zhí)行完畢時才開始執(zhí)行师坎,例如異步Ajax恕酸、DOM事件,setTimeout等胯陋。

微任務(wù)

微任務(wù)是ES6和Node環(huán)境下的蕊温,主要 API 有:Promise,process.nextTick遏乔。

微任務(wù)的執(zhí)行在宏任務(wù)的同步任務(wù)之后义矛,在異步任務(wù)之前。

參考文檔

[1]你所不知道的 HSTS:?http://t.cn/AiR8pTqx

[2]詳見這篇文章:?http://t.cn/AiR8pnEC

[3]MIME:?http://t.cn/AiR8prtm

[4]語法規(guī)范:?http://t.cn/AiR80GdO

[5]這篇文章:?http://t.cn/AiR80c1k

[6]what-happens-when-zh_CN:?http://t.cn/AiR80xb5

[7]Tags to DOM:http://t.cn/AiR80djX

[8]徹底理解瀏覽器的緩存機制:?http://t.cn/AiR8Ovob

[9]瀏覽器的工作原理:新式網(wǎng)絡(luò)瀏覽器幕后揭秘: http://t.cn/AiR8Oz06

[10]深入淺出瀏覽器渲染原理:?http://t.cn/AiR8O4fO

[11]js引擎的執(zhí)行過程(一):http://t.cn/AiR8Ot3s

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盟萨,一起剝皮案震驚了整個濱河市凉翻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捻激,老刑警劉巖制轰,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異胞谭,居然都是意外死亡垃杖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門丈屹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缩滨,“玉大人,你說我怎么就攤上這事泉瞻÷雎” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵袖牙,是天一觀的道長侧巨。 經(jīng)常有香客問我,道長鞭达,這世上最難降的妖魔是什么司忱? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任皇忿,我火速辦了婚禮,結(jié)果婚禮上坦仍,老公的妹妹穿的比我還像新娘鳍烁。我一直安慰自己,他們只是感情好繁扎,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布幔荒。 她就那樣靜靜地躺著,像睡著了一般梳玫。 火紅的嫁衣襯著肌膚如雪爹梁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天提澎,我揣著相機與錄音姚垃,去河邊找鬼。 笑死盼忌,一個胖子當(dāng)著我的面吹牛积糯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谦纱,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼絮宁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了服协?” 一聲冷哼從身側(cè)響起绍昂,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎偿荷,沒想到半個月后窘游,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡跳纳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年忍饰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寺庄。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡艾蓝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出斗塘,到底是詐尸還是另有隱情赢织,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布馍盟,位于F島的核電站于置,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贞岭。R本人自食惡果不足惜八毯,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一搓侄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧话速,春花似錦讶踪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至活合,卻和暖如春雏婶,著一層夾襖步出監(jiān)牢的瞬間物赶,已是汗流浹背白指。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留酵紫,地道東北人告嘲。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像奖地,于是被迫代替她去往敵國和親橄唬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容