一劲装、輸入網(wǎng)址
如:baidu.com
二、DNS(Domain Name Server-域名服務器)解析
互聯(lián)網(wǎng)上設(shè)備通信都要遵循IP協(xié)議昌简,它規(guī)定了每臺設(shè)備都要有唯一的IP地址占业,單純數(shù)字的IP地址難以記憶,于是產(chǎn)生了用戶更方便記憶的由字符構(gòu)成的域名纯赎,為了方便性和可用性谦疾,DNS解析實現(xiàn)了域名到對應IP地址的轉(zhuǎn)換,而DNS的本質(zhì)就是一組鍵值對犬金,鍵名就是域名念恍,如www.baidu.com,值就是IP地址佑附,如119.75.217.109樊诺。對于用戶來說,DNS解析實際上就是尋找哪臺機器上有你需要的資源的過程音同。
DNS查詢有兩種方式:遞歸和迭代词爬。
DNS客戶端設(shè)置使用的DNS服務器一般都是遞歸服務器,負責全權(quán)處理客戶端的DNS查詢請求权均,直到返回最終結(jié)果顿膨。
DNS服務器之間一般采用迭代查詢方式。
我們只需要了解DNS遞歸查詢叽赊。
- 瀏覽器緩存:用戶在瀏覽器輸入www.baidu.com恋沃,如果之前訪問過該主機且未超過瀏覽器的緩存時間,可直接使用瀏覽器緩存的DNS必指。
- 系統(tǒng)緩存:如果瀏覽器緩存里沒有記錄囊咏,瀏覽器會做系統(tǒng)調(diào)用,獲取系統(tǒng)中的緩存記錄塔橡。
- 路由器緩存:如果系統(tǒng)緩存中同樣沒有記錄梅割,需要繼續(xù)查找路由器緩存。
- 互聯(lián)網(wǎng)服務提供商(ISP)的緩存:路由器中未找到記錄會繼續(xù)查找ISP中的緩存葛家。
- 若以上本地DNS中都沒有緩存記錄户辞,那么就會開始DNS遞歸搜索。首先本地DNS向根域名服務器發(fā)出請求癞谒,無結(jié)果底燎。注意:
www.baidu.com
的網(wǎng)址實際上是www.baidu.com.
刃榨,com后的.
對應的就是根域名服務器,只是默認情況下所有網(wǎng)址最后一位都是.
双仍,為了方便用戶通常都省略枢希,瀏覽器請求DNS時會自動加上。 - 本地DNS向
com
頂級域名服務器發(fā)出請求朱沃,無結(jié)果晴玖。 - 本地DNS向
baidu.com
權(quán)威域名服務器發(fā)出請求,無結(jié)果为流。 - 本地DNS向
www.baidu.com
域名服務器發(fā)出請求,www.baidu.com域名服務器查到了對應的IP地址119.75.217.109并將地址反饋給了本地DNS让簿,本地DNS得到了這個IP地址敬察,存入自身緩存并反饋給了瀏覽器。
注意:
- 網(wǎng)址的解析是一個從右向左的過程尔当,看似步驟繁多莲祸,實際完成這一系列行為只需要幾毫秒的時間。
- DNS返回的IP地址并不是每次都一樣椭迎,真實的互聯(lián)網(wǎng)世界背后存在成千上萬臺服務器甚至更多锐帜,用戶只需要服務器處理他的需求而并不在意是哪臺機器完成了這一過程,所以DNS能做的就是返回一個合適的機器IP給用戶以達到DNS負載均衡畜号,又叫做重定向缴阎。
三、瀏覽器與服務器通過三次握手(SYN,SYN/ACK,ACK)建立TCP連接
Q:為什么是三次握手而不是兩次握手或四次握手或更多呢简软?
A:三次握手更為穩(wěn)妥蛮拔。
故事一:
革命戰(zhàn)爭影片中,呼號為黃河的一方想找呼號叫長江的一方說事痹升,于是觀眾會聽到這么一段對話:
“長江長江建炫,我是黃河,聽到請回答疼蛾「氐”
“黃河黃河,我是長江察郁,我聽到了你衍慎,請回答∩”
“長江長江西饵,我是黃河,我聽到了你鳞芙,現(xiàn)在請你收報眷柔∑谙海”
- 第一次握手:黃河發(fā)起呼叫,長江收到了驯嘱。這時長江可以確認的是镶苞,黃河的發(fā)信機和自己的收信機是好的,否則的話他收不到長江的呼叫鞠评;黃河能確認什么呢茂蚓?他什么也不能確認,有可能自己的電臺除了指示燈是好的剃幌,其它都是壞的聋涨,他在對著一臺鐵疙瘩發(fā)功。
- 第二次握手:長江回應负乡,黃河收到了牍白。這時黃河可以確認的是,自己和長江的收發(fā)信機都是好的抖棘,否則的話他收不到長江的回應信號茂腥。這時黃河可以說正事了嗎?還不能切省,雖然長江發(fā)出了回應最岗,但他并不能確認自己的發(fā)信機和黃河的收信機都是好的。
- 第三次握手:黃河對長江的回應進行回應朝捆。這時黃河很清楚般渡,雙方收發(fā)信機都是好的,自己的這次回應長江肯定能收到右蹦,這個回應的目的只是消除長江對黃河的收信機和長江自己的發(fā)信機的擔心诊杆。然后,黃河不必等長江的再次回應就可以說正事何陆。
故事二:
戰(zhàn)爭態(tài)勢:駐扎在兩個山頭上的紅1團和紅2團分別有兩個營晨汹,而在山谷的藍團有三個營,若紅1團和紅2團孤軍下山作戰(zhàn)會失敗贷盲,而兩個團同時進攻就會勝利淘这,對于紅方來說,問題的關(guān)鍵是要同時發(fā)起進攻巩剖。
戰(zhàn)爭準備過程:紅1團團長找了個傳令兵铝穷,命令他跑到紅2團,告訴紅2團團長明早9時發(fā)起進攻佳魔。傳令兵沒有被藍團俘虜曙聂,成功地跑到了紅2團的山頭,告訴紅2團團長明早9時兩個團同時進攻鞠鲜。紅2團團長一邊握著傳令兵的手激動地說“太好了宁脊!我早就等著這個消息呢断国!”,一邊心里暗自核計“雖然我知道了這個消息榆苞,但是紅1團的團長并不知道我已經(jīng)知道了稳衬,誰都知道傳令兵有可能被俘,消息很有可能傳不過來坐漏,若明天總攻前薄疚,紅1團團長不知道我已經(jīng)得到了消息,他一定不會貿(mào)然進攻的赊琳,換成我也不會”街夭。于是,紅2團團長對傳令兵說“兄弟躏筏,你辛苦了莱坎,先抽袋煙吧,抽完后再辛苦你跑回去寸士,告訴你們團長,說我已經(jīng)得到消息了碴卧,明天按時進攻弱卡。”
傳令兵又跑回到紅1團住册,僥幸又沒被藍團俘獲婶博,他告訴紅1團團長有關(guān)紅2團團長已經(jīng)獲知明早進攻的消息,但紅1團團長明早敢發(fā)起攻擊嗎?他不敢,因為他心里清楚筐骇,紅2團團長并不知道他(紅1團團長)已經(jīng)知道了“紅2團團長已獲知明早9時發(fā)起攻擊”這個消息贤旷,紅1團團長繼續(xù)想,如果是他本人是紅2團團長诵肛,就不會貿(mào)然攻擊,因為自己已經(jīng)獲知明早9時發(fā)起攻擊這件事,對方未必知道岸晦,而有可能因為傳令兵回團時被抓,敵人反而知道了睛藻,自己貿(mào)然攻擊启上,有可能就會失敗。于是店印,紅1團團長對傳令兵說“兄弟冈在,你辛苦了,先抽袋煙吧按摘,抽完后再辛苦你跑一趟紅2團包券,告訴他們團長纫谅,就說我已經(jīng)知道他已經(jīng)知道了明早9點進攻這件事,讓他放心地打吧兴使∠狄耍”
寫到這里你已經(jīng)猜到了,即使傳令兵再次來到紅2團发魄,紅2團團長也不敢開戰(zhàn)盹牧,還是要傳令兵再次回紅1團報信,因為紅2團團長擔心紅1團團長不知道他(紅2團團長)已經(jīng)知道了紅1團團長知道他(紅2團團長)知道明早9點發(fā)生攻擊的事励幼。
回到三次握手問題上汰寓,紅1團和紅2團其實就是通信的雙方,這場永遠也達不成協(xié)議的戰(zhàn)斗苹粟,說明了一個重要的通信道理:世界上不存在完全可靠的通信協(xié)議有滑。三次握手成功后,握手成功后的設(shè)備故障嵌削、干擾或話務員死亡等無數(shù)種可能性會導致通信失敗毛好,三次握手成功只說明了之前的通信條件和環(huán)境,而不能決定和預測之后的通信條件和環(huán)境苛秕,通信協(xié)議只能做到盡可能的可靠肌访,而不能做到理論上的完全可靠。
言歸正傳:謝希仁版《計算機網(wǎng)絡》中的例子是這樣的艇劫,“已失效的連接請求報文段”的產(chǎn)生在這樣一種情況下:client發(fā)出的第一個連接請求報文段并沒有丟失吼驶,而是在某個網(wǎng)絡結(jié)點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達server店煞。本來這是一個早已失效的報文段蟹演。但server收到此失效的連接請求報文段后,就誤認為是client再次發(fā)出的一個新的連接請求顷蟀。于是就向client發(fā)出確認報文段酒请,同意建立連接。假設(shè)不采用“三次握手”鸣个,那么只要server發(fā)出確認蚌父,新的連接就建立了。由于現(xiàn)在client并沒有發(fā)出建立連接的請求毛萌,因此不會理睬server的確認苟弛,也不會向server發(fā)送數(shù)據(jù)。但server卻以為新的運輸連接已經(jīng)建立阁将,并一直等待client發(fā)來數(shù)據(jù)膏秫。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生缤削。例如剛才那種情況窘哈,client不會向server的確認發(fā)出確認。server由于收不到確認亭敢,就知道client并沒有要求建立連接滚婉。”這個例子很清晰的闡釋了“三次握手”對于建立可靠連接的意義帅刀。
四让腹、瀏覽器向web服務器發(fā)送HTTP請求
發(fā)送HTTP請求的過程就是構(gòu)建HTTP請求報文并通過TCP協(xié)議中發(fā)送到服務器指定端口(HTTP協(xié)議80/8080, HTTPS協(xié)議443)。
HTTP請求報文是由三部分組成: 請求行, 請求報頭和請求正文扣溺。
-
請求行:
格式:Method Request-URL HTTP-Version CRLF
例子:GET index.html HTTP/1.1
常用的方法有: GET, POST, PUT, DELETE, OPTIONS, HEAD, TRACE骇窍,一般的瀏覽器只能發(fā)起GET或POST請求。
(1)GET
當我們通過在瀏覽器的地址欄中直接輸入網(wǎng)址的方式去訪問網(wǎng)頁的時候锥余,瀏覽器默認采用的就是 GET 方法向服務器獲取資源腹纳。但用GET方法提交的表單數(shù)據(jù)只經(jīng)過了簡單的編碼,同時它將作為URL的一部分向服務器發(fā)送驱犹,而URL具有長度限制嘲恍,即GET方式提交的數(shù)據(jù)大小有限制,如<Http://localhost/login.php?username=aa&password=1234>
雄驹,很容易辨認出表單提交的內(nèi)容蛔钙,因此,如果使用GET方法來提交表單數(shù)據(jù)就存在著安全隱患荠医。
(2)POST
是GET的一個替代方法,主要是向Web服務器提交表單數(shù)據(jù)桑涎,尤其是大批量的數(shù)據(jù)彬向。POST方法克服了GET方法的一些缺點。通過POST方法提交表單數(shù)據(jù)時攻冷,數(shù)據(jù)不是作為URL請求的一部分而是作為標準數(shù)據(jù)放在HTTP的body中傳送給Web服務器娃胆,這就克服了GET方法中的信息無法保密和數(shù)據(jù)量太小的缺點。因此等曼,出于安全的考慮以及對用戶隱私的尊重里烦,通常表單提交時采用POST方法。
(3)HEAD
HEAD 方法與 GET 方法幾乎是相同的禁谦,它們的區(qū)別在于 HEAD 方法只是請求消息報頭胁黑,而不是完整的內(nèi)容。對于 HEAD 請求的回應部分來說州泊,它的 HTTP 頭部中包含的信息與通過 GET 請求所得到的信息是相同的丧蘸。利用這個方法,不必傳輸整個資源內(nèi)容遥皂,就可以得到 Request-URI 所標識的資源的信息力喷。這個方法通常被用于測試超鏈接的有效性刽漂,是否可以訪問,以及最近是否更新弟孟。
注意:在 HTML 文檔中贝咙,書寫 get 和 post,大小寫都可以拂募,但在 HTTP 協(xié)議中的 GET 和 POST 只能是大寫形式庭猩。
-
請求報頭:允許客戶端向服務器傳遞請求的附加信息和客戶端自身的信息。
客戶端不一定特指瀏覽器没讲,有時候也可使用Linux下的CURL命令以及HTTP客戶端測試工具等眯娱。
常見的請求報頭有:Accept, Accept-Charset, Accept-Encoding, Accept-Language, Content-Type,Connection, Authorization, Cookie, User-Agent
等。Accept用于指定客戶端用于接受哪些類型的信息爬凑,Accept-Encoding與Accept類似徙缴,它用于指定接受的編碼方式。Connection設(shè)置為Keep-alive用于告訴客戶端本次HTTP請求結(jié)束之后并不需要關(guān)閉TCP連接嘁信,這樣可以使下次HTTP請求使用相同的TCP通道于样,節(jié)省TCP連接建立的時間,keep-alive不會永久保持連接潘靖,可在不同的服務器軟件中設(shè)定這個時間穿剖。
-
請求正文:當使用POST, PUT等方法時,通常需要客戶端向服務器傳遞數(shù)據(jù)卦溢。這些數(shù)據(jù)就儲存在請求正文中糊余。在請求報頭中有一些與請求正文相關(guān)的信息,例如: 現(xiàn)在的Web應用通常采用Rest架構(gòu)单寂,請求的數(shù)據(jù)格式一般為json贬芥。這時就需要設(shè)置
Content-Type: application/json
。
五宣决、服務器處理請求并返回HTTP報文
后端從在固定的端口接收到TCP報文開始蘸劈,會對TCP連接進行處理,對HTTP協(xié)議進行解析尊沸,并按照報文格式進一步封裝成HTTP Request對象威沫,供上層使用。
HTTP響應報文是由三部分組成: 狀態(tài)行, 響應報頭和響應報文洼专。
-
狀態(tài)行:包含協(xié)議版本棒掠、狀態(tài)描述、狀態(tài)代碼屁商。
格式:HTTP-Version Status-Code Reason-Phrase CRLF
示例:HTTP/1.1 200 OK
協(xié)議版本:使用http1.0還是其他版本
狀態(tài)描述:給出了關(guān)于狀態(tài)代碼的簡短的文字描述句柠。比如狀態(tài)代碼為200時的描述為 ok
狀態(tài)代碼:由三位數(shù)組成,第一個數(shù)字定義了響應類別,且有五種可能取值溯职。
1XX:指示信息–表示請求已接收精盅,繼續(xù)處理。
2xx:成功–表示請求已被成功接收谜酒、理解叹俏、接受。
3xx:重定向–要完成請求必須進行更進一步的操作僻族。
4xx:客戶端錯誤–請求有語法錯誤或請求無法實現(xiàn)粘驰。
5xx:服務器端錯誤–服務器未能實現(xiàn)合法的請求。
平時遇到比較常見的狀態(tài)碼有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500述么。
其中:301表示永久重定向響應蝌数,這樣瀏覽器就會訪問 http://www.baidu.com 而不是http://baidu.com ,服務器一定要重定向而不是直接發(fā)送用戶想看的網(wǎng)頁內(nèi)容的原因如下:
1度秘、搜索引擎的排名——如果一個頁面有兩個地址顶伞,就像 http://www.yy.com 和 http://yy.com ,搜索引擎會認為它們是兩個網(wǎng)站剑梳,結(jié)果造成每個搜索鏈接都減少從而降低排名唆貌。而搜索引擎知道301永久重定向是什么意思,這樣就會把訪問帶 www 的和不帶 www 的地址歸到同一個網(wǎng)站排名下垢乙,同時讓訪客自動跳轉(zhuǎn)到主站點锨咙。
2、緩存友好性——當一個頁面有好幾個名字時追逮,它可能會在緩存里出現(xiàn)好幾次酪刀,造成緩存友好性變差。
3钮孵、網(wǎng)站調(diào)整——如改變網(wǎng)頁目錄結(jié)構(gòu)骂倘。
4、網(wǎng)站被移到一個新地址油猫。
5、網(wǎng)頁擴展名改變——如應用需要把.php改成.html或.shtml柠偶。
在3情妖、4、5這三種情況下如果不做重定向诱担,用戶收藏夾或搜索引擎數(shù)據(jù)庫中舊地址只能讓訪客得到一個404頁面錯誤信息毡证,流量白白喪失。
301和302的區(qū)別:
301和302狀態(tài)碼都表示重定向蔫仙。
共同點:
瀏覽器在拿到服務器返回的這個狀態(tài)碼后會自動跳轉(zhuǎn)到一個新的 URL 地址料睛,這個地址可以從響應的 Location 首部中獲取(用戶看到的效果就是他輸入的地址 A 瞬間變成了另一個地址 B)。
不同點:
301:永久重定向——表示舊地址 A 的資源已經(jīng)被永久移除(這個資源不可訪問了)恤煞,搜索引擎在抓取新內(nèi)容的同時也將舊的網(wǎng)址交換為重定向之后的網(wǎng)址屎勘。使用301狀態(tài)碼進行頁面跳轉(zhuǎn)的大致場景如下:
(1)域名到期不想續(xù)費(或者發(fā)現(xiàn)了更適合網(wǎng)站的域名),想換個域名居扒。
(2)在搜索引擎的搜索結(jié)果中出現(xiàn)了不帶www的域名概漱,而帶www的域名卻沒有收錄,這個時候可以用301重定向來告訴搜索引擎我們目標的域名是哪一個喜喂。
(3)空間服務器不穩(wěn)定瓤摧,換空間的時候。
302:臨時重定向——表示舊地址 A 的資源還在(仍然可以訪問)玉吁,這個重定向只是臨時地從舊地址 A 跳轉(zhuǎn)到地址 B照弥,搜索引擎會抓取新的內(nèi)容而保存舊的網(wǎng)址。
此時瀏覽器知道了正確的訪問地址进副,會向服務器發(fā)送另一個http請求这揣。
-
響應報頭:由關(guān)鍵字:值對組成,每行一對敢会。
HTTP最常見響應報頭如下:
1曾沈、Cache頭域
(1)Date:
作用:生成消息的具體時間和日期,即當前的GMT時間鸥昏。
例如:Date: Sun, 17 Mar 2013 08:12:54 GMT
(2)Expires:
作用: 瀏覽器會在指定過期時間內(nèi)使用本地緩存塞俱,指明應該在什么時候認為文檔已經(jīng)過期,從而不再緩存它吏垮。
例如:Expires: Thu, 19 Nov 1981 08:52:00 GMT
(3)Vary
作用:告訴緩存服務器按照Vary指定的頭的內(nèi)容分別緩存不同的版本障涯,
例如:Vary: Accept-Encoding
,根據(jù)Accept-Encoding頭值的不同緩存不同的版本膳汪,Accept-Encoding的值也作為參數(shù)計算hash唯蝶,如果客戶端直接訪問源服務器,Vary就沒有意義了遗嗽。
2粘我、Cookie/Login 頭域
(1)P3P
作用: 用于跨域設(shè)置Cookie, 這樣可以解決iframe跨域訪問cookie的問題
例如:P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR
(2)Set-Cookie
作用: 非常重要的header, 用于把cookie 發(fā)送到客戶端瀏覽器, 每一個寫入cookie都會生成一個Set-Cookie.
例如:Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/
3痹换、Entity實體頭域:
實體內(nèi)容的屬性征字,包括實體信息類型,長度娇豫,壓縮方法匙姜,最后一次修改時間,數(shù)據(jù)有效性等冯痢。
(1)ETag:
作用: 和If-None-Match 配合使用氮昧。 (實例請看上節(jié)中If-None-Match的實例)
例如:ETag: “03f2b33c0bfcc1:0”
(2)Last-Modified:
作用: 用于指示資源的最后修改日期和時間框杜。(實例請看上節(jié)的If-Modified-Since的實例)
例如:Last-Modified: Wed, 21 Dec 2011 09:09:10 GMT
(3)Content-Type:
作用:WEB服務器告訴瀏覽器自己響應的對象的類型和字符集,
例如:
Content-Type: text/html; charset=utf-8 Content-Type:text/html;charset=GB2312 Content-Type: image/jpeg
(4)Content-Length:
指明實體正文的長度,以字節(jié)方式存儲的十進制數(shù)字來表示袖肥。在數(shù)據(jù)下行的過程中咪辱,Content-Length的方式要預先在服務器中緩存所有數(shù)據(jù),然后所有數(shù)據(jù)再一股腦兒地發(fā)給客戶端昭伸。
例如:Content-Length: 19847
(5)Content-Encoding:
作用:文檔的編碼(Encode)方法梧乘。一般是壓縮方式。
WEB服務器表明自己使用了什么壓縮方法(gzip庐杨,deflate)壓縮響應中的對象选调。利用gzip壓縮文檔能夠顯著地減少HTML文檔的下載時間。
例如:Content-Encoding:gzip
(6)Content-Language:
作用: WEB服務器告訴瀏覽器自己響應的對象的語言者
例如:Content-Language:da
4灵份、Miscellaneous 頭域
(1)Server:
作用:指明HTTP服務器的軟件信息
例如:Apache/2.2.8 (Win32) PHP/5.2.5
(2)X-Powered-By:
作用:表示網(wǎng)站是用什么技術(shù)開發(fā)的
例如:X-Powered-By: PHP/5.2.5
5仁堪、Transport頭域
(1)Connection:
例如:Connection: keep-alive
當一個網(wǎng)頁打開完成后,客戶端和服務器之間用于傳輸HTTP數(shù)據(jù)的TCP連接不會關(guān)閉填渠,如果客戶端再次訪問這個服務器上的網(wǎng)頁弦聂,會繼續(xù)使用這一條已經(jīng)建立的連接
例如:Connection: close
代表一個Request完成后,客戶端和服務器之間用于傳輸HTTP數(shù)據(jù)的TCP連接會關(guān)閉氛什, 當客戶端再次發(fā)送Request莺葫,需要重新建立TCP連接。
6枪眉、Location頭域
(1)Location:
作用: 用于重定向一個新的位置捺檬, 包含新的URL地址
- 響應正文:服務器返回給瀏覽器的文本信息,通常HTML贸铜,CSS堡纬,JS,圖片等文件就放在這一部分蒿秦。
六烤镐、瀏覽器緩存、解析并渲染頁面
瀏覽器緩存:包括頁面html緩存和圖片棍鳖、js炮叶、css、flash等資源的緩存渡处。
解析和渲染:顯示頁面是一個從上往下邊解析邊渲染的過程镜悉,首先瀏覽器解析HTML文件構(gòu)建DOM樹,先執(zhí)行head標簽里的內(nèi)容骂蓖,再執(zhí)行body里的积瞒,一行行渲染下去川尖,然后解析CSS文件構(gòu)建規(guī)則樹登下,解析完成后瀏覽器引擎會通過DOM樹和CSS規(guī)則樹來構(gòu)造渲染樹茫孔,等到渲染樹構(gòu)建完成,盒模型位置被芳、大小缰贝、顏色、字體等確認下來后畔濒,瀏覽器開始布局渲染樹并將其繪制到屏幕上剩晴。
JS的解析是由瀏覽器中的JS解析引擎完成的,JS是單線程運行侵状,同一個時間內(nèi)只能做一件事赞弥,所有的任務都需要排隊,前一個任務結(jié)束趣兄,后一個任務才能開始绽左。但某些任務比較耗時,所以需要一種機制可以先執(zhí)行排在后面的任務艇潭,這就是:同步任務和異步任務拼窥。JS的執(zhí)行機制就可以看做是一個主線程加上一個任務隊列。同步任務就是放在主線程上執(zhí)行的任務蹋凝,異步任務是放在任務隊列中的任務鲁纠。所有的同步任務在主線程上執(zhí)行,形成一個執(zhí)行棧;異步任務有了運行結(jié)果就會在任務隊列中放置一個事件鳍寂;腳本運行時先依次運行執(zhí)行棧改含,然后會從任務隊列里提取事件,運行任務隊列中的任務伐割,這個過程是不斷重復的候味,所以又叫做事件循環(huán)。
瀏覽器在解析過程中隔心,如果遇到請求外部資源時白群,如圖像、JS等硬霍。瀏覽器將下載該資源帜慢。請求過程是異步的,并不會影響HTML文檔進行加載唯卖,但是當文檔加載過程中遇到JS文件粱玲,HTML文檔會掛起渲染過程,不僅要等到文檔中JS文件加載完畢還要等待解析執(zhí)行完畢拜轨,才會繼續(xù)HTML的渲染過程抽减。原因是因為JS有可能修改DOM結(jié)構(gòu),這就意味著JS執(zhí)行完成前橄碾,后續(xù)所有資源的下載是沒有必要的卵沉,這就是JS阻塞后續(xù)資源下載的根本原因颠锉,即無論當前JS代碼是內(nèi)嵌還是在外部文件中,頁面的下載和渲染都必須停下來等待腳本執(zhí)行完成史汗,JS執(zhí)行過程越久琼掠,瀏覽器等待響應用戶輸入的時間就越長,所以盡量把JS放在底部可以起到性能優(yōu)化效果停撞,除此之外還可通過設(shè)置script標簽的defer或async屬性瓷蛙、合并腳本等方法進行優(yōu)化。
CSS文件的加載不影響JS文件的加載戈毒,但是卻影響JS文件的執(zhí)行艰猬。JS代碼執(zhí)行前瀏覽器必須保證CSS文件已經(jīng)下載并加載完畢。
注意:以上整個解析和渲染過程中會涉及到reflows(回流)和repaints(重繪)的概念埋市,就某些瀏覽器如Opera而言姥宝,大部分的reflow將導致頁面重新渲染,其變化涉及到部分甚至是整個頁面的布局恐疲,而repaint則導致瀏覽器必須驗證DOM樹上其他節(jié)點元素的可見性腊满。reflow和repaint過程非常消耗性能,尤其在移動設(shè)備上培己,會破壞用戶體驗碳蛋,造成頁面卡頓,所以應盡可能減少reflow和repaint省咨。
導致回流的原因:
- 調(diào)整窗口大小
- 改變字體
- 增加或移除樣式表
- 內(nèi)容變化肃弟,如在input框中輸入文字
- 激活CSS偽類,如hover
- 操作class屬性
- 腳本操作DOM
- 計算offsetWidth和offsetHeight屬性
- 設(shè)置style屬性的值
如何避免回流或?qū)⑺鼈儗π阅艿挠绊懡档阶畹停?/strong>
- 盡可能在DOM樹最末端通過改變元素的class名的方式設(shè)定元素的樣式:回流會順行或逆行傳遞給周圍的節(jié)點零蓉,在DOM樹里改變class限制了回流的范圍笤受,使其影響盡可能少的節(jié)點。
- 避免設(shè)置多項內(nèi)聯(lián)樣式:因為每個內(nèi)聯(lián)樣式都會造成回流敌蜂,樣式應合并在一個外部類箩兽,這樣當該元素的class屬性被操控時只會產(chǎn)生一個回流。
- 應用元素的動畫使用position屬性的absolute或fixed值:這樣設(shè)置不影響其他元素的布局章喉,只會導致重繪而不是完整回流汗贫。
- 犧牲平滑度換取速度:你可能想每次1px移動一個動畫,但是此動畫及隨后的回流使用了100%的CPU秸脱,動畫看上去就會是跳動的落包,因為瀏覽器正在與更新回流做斗爭。而動畫元素每次移動3px摊唇,在非掣烙快的機器上看起來平滑度低了,但它不會導致CPU在較慢的機器和移動設(shè)備中抖動巷查。
- 避免使用table布局:table是個和罕見的可以影響在它們之前已經(jīng)進入的DOM元素的顯示的元素有序。想象一下撮竿,因為表格最后一個單元格的內(nèi)容過寬而導致縱列大小完全改變。這就是為什么所有的瀏覽器都逐步地不支持table表格的渲染笔呀。另外一個原因說明表格布局很糟糕,根據(jù)Mozilla髓需,一些小的變化將導致表格(table)中的所有其他節(jié)點回流许师。
- 避免使用CSS的JS表達式:因為他們每次都重新計算全部或部分文檔而導致每秒產(chǎn)生成千上萬次回流。
- 設(shè)置
box-sizing: border-box;
把標準盒模型轉(zhuǎn)換為IE盒模型僚匆,告訴瀏覽器去理解你設(shè)置的邊框和內(nèi)邊距的值是包含在width內(nèi)的微渠。設(shè)置后,即使padding或者border發(fā)生了改變咧擂,盒子寬高不會發(fā)生變化逞盆,只會重繪,不會回流松申。
七云芦、連接結(jié)束
以上是在瀏覽器中輸入一個URL到頁面展現(xiàn)的過程。
服務器發(fā)給瀏覽器的文件中會帶有 Expires(有效期) 或 Cache-Control(緩存控制) 說明文件什么時候失效贸桶,有效期內(nèi)瀏覽器直接使用本地文件,不發(fā)請求舅逸。服務器響應中會帶有文件的最后修改時間或 Etag,瀏覽器發(fā)送重復請求會帶上這些信息皇筛,服務器判斷沒有變化會發(fā)送304狀態(tài)碼琉历,讓瀏覽器使用本地緩存。
參考資料:
- 從URL到頁面加載發(fā)生了什么
- 從URL到頁面展現(xiàn)發(fā)生了什么
- 維基百科-域名系統(tǒng)
- 通信協(xié)議中三次握手的故事
- HTTP-請求水醋、響應旗笔、緩存
- 張鑫旭-回流與重繪:CSS性能讓JavaScript變慢?
推薦資料: