開始上網(wǎng)来候,輸入 url
當(dāng)我們開始輸入 url 的時(shí)候,瀏覽器就已經(jīng)開始匹配 url 左敌,從歷史紀(jì)錄,書簽等俐镐,找到已經(jīng)輸入的字符串可能對(duì)應(yīng)的 url 矫限,然后給出智能提示,自動(dòng)補(bǔ)全等佩抹。
![](http://or3233yyd.bkt.clouddn.com//17-8-9/69469932.jpg)
解析URL
瀏覽器通過 URL 能夠知道下面的信息:
Protocol "http"
使用HTTP協(xié)議Resource "/"
請(qǐng)求的資源是主頁(index)
輸入的是 URL 還是搜索的關(guān)鍵字叼风?
當(dāng)協(xié)議或主機(jī)名不合法時(shí),瀏覽器會(huì)將地址欄中輸入的文字傳給默認(rèn)的搜索引擎棍苹。大部分情況下无宿,在把文字傳遞給搜索引擎的時(shí)候,URL會(huì)帶有特定的一串字符枢里,用來告訴搜索引擎這次搜索來自這個(gè)特定瀏覽器孽鸡。
轉(zhuǎn)換非 ASCII 的 Unicode 字符
- 瀏覽器檢查輸入是否含有不是 a-z蹂午, A-Z,0-9彬碱, - 或者 . 的字符
- 這里主機(jī)名是 google.com 豆胸,所以沒有非ASCII的字符;如果有的話巷疼,瀏覽器會(huì)對(duì)主機(jī)名部分使用 Punycode 編碼
檢查 HSTS 列表
- 瀏覽器檢查自帶的“預(yù)加載 HSTS(HTTP嚴(yán)格傳輸安全)”列表晚胡,這個(gè)列表里包含了那些請(qǐng)求瀏覽器只使用HTTPS進(jìn)行連接的網(wǎng)站
- 如果網(wǎng)站在這個(gè)列表里,瀏覽器會(huì)使用 HTTPS 而不是 HTTP 協(xié)議嚼沿,否則估盘,最初的請(qǐng)求會(huì)使用HTTP協(xié)議發(fā)送
- 注意,一個(gè)網(wǎng)站哪怕不在 HSTS 列表里骡尽,也可以要求瀏覽器對(duì)自己使用 HSTS 政策進(jìn)行訪問遣妥。瀏覽器向網(wǎng)站發(fā)出第一個(gè) HTTP 請(qǐng)求之后,網(wǎng)站會(huì)返回瀏覽器一個(gè)響應(yīng)爆阶,請(qǐng)求瀏覽器只使用 HTTPS 發(fā)送請(qǐng)求燥透。然而,就是這第一個(gè) HTTP 請(qǐng)求辨图,卻可能會(huì)使用戶受到 downgrade attack 的威脅班套,這也是為什么現(xiàn)代瀏覽器都預(yù)置了 HSTS 列表。
瀏覽器查找 url 的 Ip 地址
- 瀏覽器檢查域名是否在緩存當(dāng)中(要查看 Chrome 當(dāng)中的緩存故河, 打開 chrome://net-internals/#dns)吱韭。
- 首先查看本地硬盤的 host 文件,查看其中有沒有和這個(gè)域名對(duì)應(yīng)的規(guī)則鱼的,如果找到理盆,就直接使用 host 中的 ip 地址。
- 如果 host 中沒能找到對(duì)應(yīng)的 ip 地址凑阶,瀏覽器會(huì)發(fā)出一個(gè) DNS 請(qǐng)求到本地 DNS 服務(wù)器猿规,即網(wǎng)絡(luò)接入提供商(中國(guó)移動(dòng),中國(guó)電信等)
- 本地 DNS 服務(wù)器查詢它的緩存記錄宙橱,如果有就直接返回查詢結(jié)果姨俩,此過程是遞歸查詢,如果沒有則會(huì)向 DNS 根服務(wù)器查詢
- 跟服務(wù)器沒有相應(yīng)的記錄時(shí)师郑,就告訴本地 DNS 服務(wù)器可以去域名服務(wù)器查詢环葵,并告知域名服務(wù)器的 IP,
- 本地服務(wù)器向域名服務(wù)器發(fā)出請(qǐng)求宝冕,在下圖中請(qǐng)求的對(duì)象是 .com 服務(wù)器张遭, .com 服務(wù)器收到請(qǐng)求后,也不會(huì)直接返回對(duì)應(yīng)關(guān)系地梨,而是告訴本地 DNS 服務(wù)器菊卷,你所查詢的域名的服務(wù)器的地址缔恳。
- 本地服務(wù)器向查詢的域名服務(wù)器發(fā)出請(qǐng)求,此時(shí)能收到相應(yīng)的域名和 IP 的地址的烁,本地 DNS 不僅要把返回的 IP 和域名返回給用戶還要把這個(gè)關(guān)系保存到緩存中褐耳,以防下次用戶請(qǐng)求時(shí),可以快速返回結(jié)果渴庆,加快了網(wǎng)絡(luò)的訪問铃芦。
![域名解析-盜圖](http://or3233yyd.bkt.clouddn.com//17-8-9/12752710.jpg)
瀏覽器向 Web 服務(wù)器發(fā)出 HTTP 請(qǐng)求
拿到域名對(duì)應(yīng)的 IP 地址之后,瀏覽器會(huì)以隨機(jī)一個(gè)( 1024 < 端口號(hào) < 65535 ) 向 Web 服務(wù)器 ( nginx ) 的 80 端口號(hào)發(fā)出 TCP 的連接請(qǐng)求襟雷,經(jīng)過各種路由設(shè)備(局域網(wǎng)除外)刃滓,
到達(dá)網(wǎng)卡,進(jìn)入到內(nèi)核的 TCP/IP 協(xié)議棧( 識(shí)別連接請(qǐng)求耸弄,解封包等 )咧虎,最終到達(dá) Web 應(yīng)用程序,建立起了 TCP/IP 連接计呈。
![](http://or3233yyd.bkt.clouddn.com//17-8-9/51034741.jpg)
建立起 TCP 連接之后砰诵,發(fā)起一個(gè) HTTP 請(qǐng)求 ( 一般常用是 get post )。
一般一個(gè) HTTP 請(qǐng)求包含:
- 請(qǐng)求的 url 協(xié)議/版本
- 請(qǐng)求頭 request header
- 請(qǐng)求體 request body
![](http://or3233yyd.bkt.clouddn.com//17-8-9/16138101.jpg)
![](http://or3233yyd.bkt.clouddn.com//17-8-9/65736963.jpg)
最后一個(gè)請(qǐng)求頭后面是空行捌显,發(fā)送回車符和換行符茁彭,通知服務(wù)器以下不再是請(qǐng)求頭
![](http://or3233yyd.bkt.clouddn.com//17-8-9/26447488.jpg)
服務(wù)器的永久重定向響應(yīng)
服務(wù)器給瀏覽器響應(yīng)一個(gè) 301 的永久重定向,這樣瀏覽器訪問 http://www.google.com 而不是 http://google.com 扶歪,這是由于搜索引擎排名的原因理肺,比如我的網(wǎng)站為了輸入方便,在進(jìn)行 DNS 解析時(shí)善镰,將 http://www.hexin.life 和 http://hexin.life 定位到了同一網(wǎng)站下妹萨,搜素引擎會(huì)認(rèn)為他們是倆個(gè)網(wǎng)站,從而造成搜索排名下降炫欺。而當(dāng) 301 重定向之后乎完,搜素引擎便會(huì)把含 www 的和不含的放在同一個(gè)網(wǎng)站排名中,而且使用 www 和非 www 時(shí)品洛,也會(huì)緩存多次树姨,所以會(huì)進(jìn)行 301 的重定向。
瀏覽器跟蹤重定向地址
再次向正確地址發(fā)送 HTTP 請(qǐng)求
服務(wù)器處理請(qǐng)求
經(jīng)過千辛萬苦毫别,終于將 http 發(fā)送到了我們的服務(wù)器娃弓。后端接到 TCP 報(bào)文開始典格,他會(huì)對(duì) tcp 連接進(jìn)行處理岛宦,對(duì) HTTP 根據(jù)協(xié)議進(jìn)行解析,按照?qǐng)?bào)文格式一步一步封裝成 HTTP request 對(duì)象耍缴,供上層使用砾肺。
![](http://or3233yyd.bkt.clouddn.com//17-8-9/67016800.jpg)
大一點(diǎn)的網(wǎng)站會(huì)請(qǐng)求到反向代理中挽霉,因?yàn)榫W(wǎng)站訪問量越來越大,網(wǎng)站速度也就變慢了变汪,此時(shí)客戶端不再直接通過 HTTP 協(xié)議訪問某網(wǎng)站的應(yīng)用服務(wù)器侠坎,而是先請(qǐng)求到 Nginx , Nginx 再請(qǐng)求應(yīng)用服務(wù)器裙盾,然后再將結(jié)果返回給客戶端实胸,這里 Nginx 的作用時(shí)反向代理服務(wù)器,同時(shí)如果一臺(tái)服務(wù)器掛了番官,只要其他服務(wù)器還在正常運(yùn)行庐完,網(wǎng)站就能正常使用。
服務(wù)器返回 HTTP 請(qǐng)求
響應(yīng)類似請(qǐng)求:
- 狀態(tài)行
- 響應(yīng)頭
- 響應(yīng)體
![](./1502292587253.png)
響應(yīng)狀態(tài)碼
- 1xx:信息性狀態(tài)碼徘熔,表示服務(wù)器已接收了客戶端請(qǐng)求门躯,客戶端可繼續(xù)發(fā)送請(qǐng)求。
100 Continue
101 Switching Protocols
- 2xx:成功狀態(tài)碼酷师,表示服務(wù)器已成功接收到請(qǐng)求并進(jìn)行處理讶凉。
200 OK 表示客戶端請(qǐng)求成功
204 No Content 成功,但不返回任何實(shí)體的主體部分
206 Partial Content 成功執(zhí)行了一個(gè)范圍(Range)請(qǐng)求
- 3xx:重定向狀態(tài)碼山孔,表示服務(wù)器要求客戶端重定向懂讯。
301 Moved Permanently 永久性重定向,響應(yīng)報(bào)文的Location首部應(yīng)該有該資源的新URL
302 Found 臨時(shí)性重定向饱须,響應(yīng)報(bào)文的Location首部給出的URL用來臨時(shí)定位資源
303 See Other 請(qǐng)求的資源存在著另一個(gè)URI域醇,客戶端應(yīng)使用GET方法定向獲取請(qǐng)求的資源
304 Not Modified 服務(wù)器內(nèi)容沒有更新,可以直接讀取瀏覽器緩存
307 Temporary Redirect 臨時(shí)重定向蓉媳。與302 Found含義一樣譬挚。302禁止POST變換為GET,但實(shí)際使用時(shí)并不一定酪呻,307則更多瀏覽器可能會(huì)遵循這一標(biāo)準(zhǔn)减宣,但也依賴于瀏覽器具體實(shí)現(xiàn)
- 4xx:客戶端錯(cuò)誤狀態(tài)碼,表示客戶端的請(qǐng)求有非法內(nèi)容玩荠。
400 Bad Request 表示客戶端請(qǐng)求有語法錯(cuò)誤漆腌,不能被服務(wù)器所理解
401 Unauthonzed 表示請(qǐng)求未經(jīng)授權(quán),該狀態(tài)代碼必須與 WWW-Authenticate 報(bào)頭域一起使用
403 Forbidden 表示服務(wù)器收到請(qǐng)求阶冈,但是拒絕提供服務(wù)闷尿,通常會(huì)在響應(yīng)正文中給出不提供服務(wù)的原因
404 Not Found 請(qǐng)求的資源不存在,例如女坑,輸入了錯(cuò)誤的URL
- 5xx:服務(wù)器錯(cuò)誤狀態(tài)碼填具,表示服務(wù)器未能正常處理客戶端的請(qǐng)求而出現(xiàn)意外錯(cuò)誤式镐。
500 Internel Server Error 表示服務(wù)器發(fā)生不可預(yù)期的錯(cuò)誤肪凛,導(dǎo)致無法完成客戶端的請(qǐng)求
503 Service Unavailable 表示服務(wù)器當(dāng)前不能夠處理客戶端的請(qǐng)求森枪,在一段時(shí)間之后柄沮,服務(wù)器可能會(huì)恢復(fù)正常
HTTP狀態(tài)碼
HTTP response codes
HTTP,HTTP2.0,SPDY,HTTPS你應(yīng)該知道的一些事
瀏覽器渲染 html
瀏覽器在解析html文件時(shí),會(huì)”自上而下“加載盟广,并在加載過程中進(jìn)行解析渲染闷串。在解析過程中,如果遇到請(qǐng)求外部資源時(shí)筋量,如圖片烹吵、外鏈的CSS、iconfont等桨武,請(qǐng)求過程是異步的年叮,并不會(huì)影響html文檔進(jìn)行加載。
- 首先是解析 HTML 構(gòu)建 DOM 樹 =>
- 解析 CSS 解析為 CSSOM =>
- 結(jié)合 DOM 和 CSSOM 生成 render tree(每個(gè)節(jié)點(diǎn)的視覺信息) =>
- 生成布局 layout =>
- 將布局繪制到屏幕
這五步中玻募,三四步比較慢生成布局和繪制合成渲染
當(dāng)文檔加載過程中遇到j(luò)s文件只损,html文檔會(huì)掛起渲染(加載解析渲染同步)的線程,不僅要等待文檔中js文件加載完畢七咧,還要等待解析執(zhí)行完畢跃惫,才可以恢復(fù)html文檔的渲染線程。因?yàn)镴S有可能會(huì)修改DOM艾栋,最為經(jīng)典的document.write爆存,這意味著,在JS執(zhí)行完成前蝗砾,后續(xù)所有資源的下載可能是沒有必要的先较,這是js阻塞后續(xù)資源下載的根本原因。所以我明平時(shí)的代碼中悼粮,js是放在html文檔末尾的闲勺。
DOM 樹
DOM 樹中的每一個(gè)需要顯示的節(jié)點(diǎn)再渲染樹中至少存在一個(gè)對(duì)應(yīng)的節(jié)點(diǎn),隱藏的 DOM 元素則沒有對(duì)應(yīng)節(jié)點(diǎn)扣猫,渲染樹中的節(jié)點(diǎn)被稱為 “幀(frames)”或“盒(boxes)”菜循,
符合 CSS 模型的定義,一旦DOM 樹和渲染樹構(gòu)建完成申尤,瀏覽器就開始顯示繪制元素
很多時(shí)候癌幕,密集的重新渲染是無法避免的,比如scroll事件的回調(diào)函數(shù)和網(wǎng)頁動(dòng)畫昧穿。
網(wǎng)頁動(dòng)畫的每一幀(frame)都是一次重新渲染勺远。每秒低于24幀的動(dòng)畫,人眼就能感受到停頓时鸵。一般的網(wǎng)頁動(dòng)畫胶逢,需要達(dá)到每秒30幀到60幀的頻率,才能比較流暢。如果能達(dá)到每秒70幀甚至80幀宪塔,就會(huì)極其流暢。
大多數(shù)顯示器的刷新頻率是60Hz囊拜,為了與系統(tǒng)一致某筐,以及節(jié)省電力,瀏覽器會(huì)自動(dòng)按照這個(gè)頻率冠跷,刷新動(dòng)畫(如果可以做到的話)南誊。
所以,如果網(wǎng)頁動(dòng)畫能夠做到每秒60幀蜜托,就會(huì)跟顯示器同步刷新抄囚,達(dá)到最佳的視覺效果。這意味著橄务,一秒之內(nèi)進(jìn)行60次重新渲染幔托,每次重新渲染的時(shí)間不能超過16.66毫秒。
一秒之間能夠完成多少次重新渲染蜂挪,這個(gè)指標(biāo)就被稱為"刷新率"重挑,英文為FPS(frame per second)。60次重新渲染棠涮,就是60FPS谬哀。
如果想達(dá)到60幀的刷新率,就意味著JavaScript線程每個(gè)任務(wù)的耗時(shí)严肪,必須少于16毫秒史煎。一個(gè)解決辦法是使用Web Worker,主線程只用于UI渲染驳糯,然后跟UI渲染不相干的任務(wù)篇梭,都放在Worker線程。
DOM 解析
<html>
<html>
<head>
<title>Web page parsing</title>
</head>
<body>
<div>
<h1>Web page parsing</h1>
<p>This is an example Web page.</p>
</div>
</body>
</html>
DOM 解析成這樣
CSS 解析
假設(shè)有下面這樣的 DOM 結(jié)構(gòu)
<doc>
<title>A few quotes</title>
<para>
Franklin said that <quote>"A penny saved is a penny earned."</quote>
</para>
<para>
FDR said <quote>"We have nothing to fear but <span>fear itself.</span>"</quote>
</para>
</doc>
CSS 文檔
/* rule 1 */ doc { display: block; text-indent: 1em; }
/* rule 2 */ title { display: block; font-size: 3em; }
/* rule 3 */ para { display: block; }
/* rule 4 */ [class="emph"] { font-style: italic; }
CSS Rule tree 時(shí)這樣
- 圖中的第4條規(guī)則出現(xiàn)了兩次酝枢,一次是獨(dú)立的很洋,一次是在規(guī)則3的子結(jié)點(diǎn)。所以隧枫,我們可以知道喉磁,建立CSS Rule Tree是需要比照著DOM Tree來的。CSS匹配DOM Tree主要是從右到左解析CSS的Selector官脓,好多人以為這個(gè)事會(huì)比較快协怒,其實(shí)并不一定。關(guān)鍵還看我們的CSS的Selector怎么寫了卑笨。
- CSS匹配HTML元素是一個(gè)相當(dāng)復(fù)雜和有性能問題的事情孕暇。所以,你就會(huì)在N多地方看到很多人都告訴你,DOM樹要小妖滔,CSS盡量用id和class隧哮,千萬不要過渡層疊下去
通過這倆個(gè)樹我們可以得到一個(gè)叫 Style Context Tree
所以,F(xiàn)irefox基本上來說是通過CSS 解析 生成 CSS Rule Tree座舍,然后沮翔,通過比對(duì)DOM生成Style Context Tree,然后Firefox通過把Style Context Tree和其Render Tree(Frame Tree)關(guān)聯(lián)上曲秉,就完成了采蚀。注意:Render Tree會(huì)把一些不可見的結(jié)點(diǎn)去除掉。而Firefox中所謂的Frame就是一個(gè)DOM結(jié)點(diǎn)承二,不要被其名字所迷惑了榆鼠。
在 Firefox 中,系統(tǒng)會(huì)針對(duì) DOM 更新注冊(cè)展示層亥鸠,作為偵聽器妆够。展示層將框架創(chuàng)建工作委托給FrameConstructor,由該構(gòu)造器解析樣式(請(qǐng)參閱樣式計(jì)算)并創(chuàng)建框架负蚊。
在 WebKit 中责静,解析樣式和創(chuàng)建呈現(xiàn)器的過程稱為“附加”。每個(gè) DOM 節(jié)點(diǎn)都有一個(gè)“attach”方法盖桥。附加是同步進(jìn)行的灾螃,將節(jié)點(diǎn)插入 DOM 樹需要調(diào)用新的節(jié)點(diǎn)“attach”方法
渲染
- 計(jì)算 CSS 樣式
- 構(gòu)建 render tree
- Layout
- 開始繪制
上圖流程中有很多連接線,這表示了Javascript動(dòng)態(tài)修改了DOM屬性或是CSS屬會(huì)導(dǎo)致重新Layout揩徊,有些改變不會(huì)腰鬼,就是那些指到天上的箭頭,比如塑荒,修改后的CSS rule沒有被匹配到熄赡,等。
Repaint
屏幕的一部分要重畫齿税,比如某個(gè)元素的 CSS 背景變了彼硫,但尺寸沒有變
Reflow
當(dāng) DOM 的變化影響了元素的幾何屬性 => 比如改變邊框?qū)挾然蛘呓o段落增加文字,導(dǎo)致行數(shù)增加 => 瀏覽器需要重新計(jì)算元素的幾何屬性凌箕,同樣其他元素的幾何屬性和位置也會(huì)收到影響拧篮,瀏覽器會(huì)使渲染樹中受到影響部分失效,并重新構(gòu)造渲染樹牵舱,發(fā)生重排串绩,完成重排后,瀏覽器會(huì)重新繪制受影響部分的元素到屏幕中芜壁,也會(huì)發(fā)生重繪礁凡。
- 樣式表越簡(jiǎn)單高氮,重排和重繪就越快。
- 重排和重繪的DOM元素層級(jí)越高顷牌,成本就越高剪芍。
- table元素的重排和重繪成本,要高于div元素
發(fā)生重繪
- 當(dāng)你增加窟蓝、刪除罪裹、修改DOM結(jié)點(diǎn)時(shí),會(huì)導(dǎo)致Reflow或Repaint
- 當(dāng)你移動(dòng)DOM的位置疗锐,或是搞個(gè)動(dòng)畫的時(shí)候。(元素位置發(fā)生改變)
- 當(dāng)你修改CSS樣式的時(shí)候费彼』或者頁面渲染初始化
- 當(dāng)你Resize窗口的時(shí)候(移動(dòng)端沒有這個(gè)問題),或是滾動(dòng)的時(shí)候箍铲。
- 當(dāng)你修改網(wǎng)頁的默認(rèn)字體時(shí)雇卷。
- 元素尺寸發(fā)生改變(邊距, 高度等)
- 注:display:none會(huì)觸發(fā)reflow颠猴,而visibility:hidden只會(huì)觸發(fā)repaint关划,因?yàn)闆]有發(fā)現(xiàn)位置變化。
渲染樹的變化的排隊(duì)與刷新
由于每次重排都行會(huì)產(chǎn)生消耗翘瓮,大多數(shù)瀏覽器通過隊(duì)列化修改并批量執(zhí)行來優(yōu)化重排過程贮折,然而,你可能會(huì)不知不覺的強(qiáng)制刷新對(duì)了要求計(jì)劃立刻執(zhí)行资盅,獲取布局的信息會(huì)導(dǎo)致隊(duì)列刷新
- offsetTop, offsetBottom, offsetWidth, offsetHeight
- scrollTop, scrollBottom, scrollWidth, scrollHeight
- clientTop, clientBottom, clientWidth, clientHeight
- getComputedStyle() =>( currentStyle in IE)
以上屬性和方法需要返回最新的布局信息调榄,因此瀏覽器不得不執(zhí)行渲染隊(duì)列中的‘待處理變化’并觸發(fā)重排以返回正確的值。
"重繪"不一定需要"重排" ---- "重排"必然導(dǎo)致"重繪"
最小化重繪和重排
- 改變樣式 => 不要一條條地改變樣式呵扛,多個(gè)改變合并 => 直接更換 CSS 的 Class
- 批量修改 DOM => 使元素脫離文檔流(隱藏顯示每庆,使用文檔片段,拷貝到一個(gè)脫離文檔的節(jié)點(diǎn)中完成后再替換) => 修改 => 帶回文檔
- 動(dòng)畫使用絕對(duì)定位今穿,使用拖放代理
- 緩存布局信息 => 偏移量缤灵,滾動(dòng)位置, 計(jì)算出的樣式等 獲取一次后賦值給局部遍歷
- 事件委托 => 減少事件處理器的數(shù)量
瀏覽器請(qǐng)求嵌在 HTML 中的資源(圖片蓝晒,視頻音頻腮出, CSS, JavaScript 等)
其實(shí)這個(gè)步驟可以并列在步驟8中芝薇,在瀏覽器顯示HTML時(shí)利诺,它會(huì)注意到需要獲取其他地址內(nèi)容的標(biāo)簽。這時(shí)剩燥,瀏覽器會(huì)發(fā)送一個(gè)獲取請(qǐng)求來重新獲得這些文件慢逾。比如我要獲取外圖片立倍,CSS,JS文件等侣滩,類似于下面的鏈接:
圖片:http://or3233yyd.bkt.clouddn.com//17-8-9/67016800.jpg
CSS式樣表:https://cdn.bootcss.com/animate.css/3.5.2/animate.css
JavaScript 文件:https://cdn.bootcss.com/jquery/3.2.1/core.js
這些地址都要經(jīng)歷一個(gè)和HTML讀取類似的過程口注。所以瀏覽器會(huì)在DNS中查找這些域名,發(fā)送請(qǐng)求君珠,重定向等等...
不像動(dòng)態(tài)頁面寝志,靜態(tài)文件會(huì)允許瀏覽器對(duì)其進(jìn)行緩存。有的文件可能會(huì)不需要與服務(wù)器通訊策添,而從緩存中直接讀取材部,或者可以放到CDN中