Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
塊的文章網(wǎng)上也是比較多的,但大多數(shù)都是講解DOM樹的渲染,對(duì)于頁面從請(qǐng)求到展示的詳細(xì)流程講解還是比較少的,而且有些說的也不容易理解,下面我將以圖文結(jié)合的形式給大伙講講。
作用
DNS 的作用就是通過域名查詢到具體的 IP。
背景
因?yàn)?IP 存在數(shù)字和英文的組合(IPv6),很不利于人類記憶,所以就出現(xiàn)了域名。你可以把域名看成是某個(gè) IP 的別名,DNS 就是去查詢這個(gè)別名的真正名稱是什么。
過程
在 TCP 握手之前就已經(jīng)進(jìn)行了 DNS 查詢,這個(gè)查詢是操作系統(tǒng)自己做的。當(dāng)你在瀏覽器中想訪問 www.test.com 時(shí),會(huì)進(jìn)行一下操作:
以上介紹的是 DNS 迭代查詢,還有種是遞歸查詢,區(qū)別就是前者是由客戶端去做請(qǐng)求,后者是由系統(tǒng)配置的 DNS 服務(wù)器做請(qǐng)求,得到結(jié)果后將數(shù)據(jù)返回給客戶端。
在進(jìn)行完DNS解析之后,接下來就是 TCP 握手,應(yīng)用層會(huì)下發(fā)數(shù)據(jù)給傳輸層,這里 TCP 協(xié)議會(huì)指明兩端的端口號(hào),然后下發(fā)給網(wǎng)絡(luò)層。網(wǎng)絡(luò)層中的 IP 協(xié)議會(huì)確定 IP 地址,并且指示了數(shù)據(jù)傳輸中如何跳轉(zhuǎn)路由器。然后包會(huì)再被封裝到數(shù)據(jù)鏈路層的數(shù)據(jù)幀結(jié)構(gòu)中,最后就是物理層面的傳輸了。
TCP建立連接的三次握手
首先假設(shè)主動(dòng)發(fā)起請(qǐng)求的一端稱為客戶端,被動(dòng)連接的一端稱為服務(wù)端。不管是客戶端還是服務(wù)端,TCP 連接建立完后都能發(fā)送和接收數(shù)據(jù),所以 TCP 是一個(gè)全雙工的協(xié)議。
起初,兩端都為 CLOSED 狀態(tài)。在通信開始前,雙方都會(huì)創(chuàng)建 TCB。 服務(wù)器創(chuàng)建完 TCB 后便進(jìn)入 LISTEN 狀態(tài),此時(shí)開始等待客戶端發(fā)送數(shù)據(jù)。
第一次握手
客戶端向服務(wù)端發(fā)送連接請(qǐng)求報(bào)文段。該報(bào)文段中包含自身的數(shù)據(jù)通訊初始序號(hào)。請(qǐng)求發(fā)送后,客戶端便進(jìn)入 SYN-SENT 狀態(tài)。
第二次握手
服務(wù)端收到連接請(qǐng)求報(bào)文段后,如果同意連接,則會(huì)發(fā)送一個(gè)應(yīng)答,該應(yīng)答中也會(huì)包含自身的數(shù)據(jù)通訊初始序號(hào),發(fā)送完成后便進(jìn)入 SYN-RECEIVED 狀態(tài)。
第三次握手
當(dāng)客戶端收到連接同意的應(yīng)答后,還要向服務(wù)端發(fā)送一個(gè)確認(rèn)報(bào)文??蛻舳税l(fā)完這個(gè)報(bào)文段后便進(jìn)入 ESTABLISHED 狀態(tài),服務(wù)端收到這個(gè)應(yīng)答后也進(jìn)入 ESTABLISHED 狀態(tài),此時(shí)連接建立成功。
第三次握手中可以包含數(shù)據(jù),通過快速打開(TFO)技術(shù)就可以實(shí)現(xiàn)這一功能。其實(shí)只要涉及到握手的協(xié)議,都可以使用類似 TFO 的方式,客戶端和服務(wù)端存儲(chǔ)相同的 cookie,下次握手時(shí)發(fā)出 cookie 達(dá)到減少 RTT 的目的。
TLS 協(xié)議位于傳輸層之上,應(yīng)用層之下,主要是對(duì)HTTP請(qǐng)求進(jìn)行加密。首次進(jìn)行 TLS 協(xié)議傳輸需要兩個(gè) RTT ,接下來可以通過 Session Resumption 減少到一個(gè) RTT。
TLS 握手過程如下圖:
通過以上步驟可知,在 TLS 握手階段,兩端使用非對(duì)稱加密的方式來通信,但是因?yàn)榉菍?duì)稱加密損耗的性能比對(duì)稱加密大,所以在正式傳輸數(shù)據(jù)時(shí),兩端使用對(duì)稱加密的方式通信。
數(shù)據(jù)在進(jìn)入服務(wù)端之前,可能還會(huì)先經(jīng)過負(fù)責(zé)負(fù)載均衡的服務(wù)器,它的作用就是將請(qǐng)求合理的分發(fā)到多臺(tái)服務(wù)器上,這時(shí)假設(shè)服務(wù)端會(huì)響應(yīng)一個(gè) HTML 文件。
首先瀏覽器會(huì)判斷狀態(tài)碼是什么,如果是 200 那就繼續(xù)解析,如果 400 或 500 的話就會(huì)報(bào)錯(cuò),如果 300 的話會(huì)進(jìn)行重定向,這里會(huì)有個(gè)重定向計(jì)數(shù)器,避免過多次的重定向,超過次數(shù)也會(huì)報(bào)錯(cuò)。
瀏覽器解析
瀏覽器開始解析文件,如果是 gzip 格式的話會(huì)先解壓一下,然后通過文件的編碼格式去解碼文件。
文件解碼成功后會(huì)正式開始渲染流程,先會(huì)根據(jù) HTML 構(gòu)建 DOM 樹,有 CSS 的話會(huì)去構(gòu)建 CSSOM 樹。如果遇到 script 標(biāo)簽的話,會(huì)判斷是否存在 async 或者 defer ,前者會(huì)并行進(jìn)行下載并執(zhí)行 JS,后者會(huì)先下載文件,然后等待 HTML 解析完成后順序執(zhí)行。
如果以上都沒有,就會(huì)阻塞住渲染流程直到 JS 執(zhí)行完畢。遇到文件下載的會(huì)去下載文件,這里如果使用 HTTP/2 協(xié)議的話會(huì)極大的提高多圖的下載效率。
CSSOM 樹和 DOM 樹構(gòu)建完成后會(huì)開始生成 Render 樹,這一步就是確定頁面元素的布局、樣式等等諸多方面的東西
在生成 Render 樹的過程中,瀏覽器就開始調(diào)用 GPU 繪制,合成圖層,將內(nèi)容顯示在屏幕上了。
總的來說,今天這篇文章主要是帶著大家從 DNS 查詢開始到渲染出畫面完整的了解一遍過程,里面涉及到DNS、HTTP、TLS、負(fù)載均衡和瀏覽器渲染等等內(nèi)容,算不上非常詳細(xì),但如果面試的時(shí)候能說出來這些,相信面試官也會(huì)對(duì)你刮目相看的。
語義化是指根據(jù)內(nèi)容的結(jié)構(gòu)化(內(nèi)容語義化),選擇合適的標(biāo)簽(代 碼語義化)。通俗來講就是用正確的標(biāo)簽做正確的事情。
語義化的優(yōu)點(diǎn)如下:
對(duì)機(jī)器友好,帶有語義的文字表現(xiàn)力豐富,更適合搜索引擎的爬蟲爬 取有效信息,有利于 SEO。除此之外,語義類還支持讀屏軟件,根據(jù) 文章可以自動(dòng)生成目錄;
對(duì)開發(fā)者友好,使用語義類標(biāo)簽增強(qiáng)了可讀性,結(jié)構(gòu)更加清晰,開發(fā) 者能清晰地看出網(wǎng)頁的結(jié)構(gòu),便于團(tuán)隊(duì)的開發(fā)與維護(hù)。
常見的語義化標(biāo)簽:
DOCTYPE 是 HTML5 中一種標(biāo)準(zhǔn)通用標(biāo)記語言的文檔類型聲明,它的目 的是告訴瀏覽器(解析器)應(yīng)該以什么樣(html 或 xhtml)的文檔類 行定義來解析文檔,不同的渲染模式會(huì)影響瀏覽器對(duì) CSS 代碼甚?JavaScript 腳本的解析。它必須聲明在 HTML?檔的第??。
瀏覽器渲染頁面的兩種模式(可通過 document.compatMode 獲取,比 如,語雀官網(wǎng)的文檔類型是 CSS1Compat):
CSS1Compat:標(biāo)準(zhǔn)模式(Strick mode),默認(rèn)模式,瀏覽器使用 W3C 的標(biāo)準(zhǔn)解析渲染頁面。在標(biāo)準(zhǔn)模式中,瀏覽器以其支持的最高標(biāo)準(zhǔn)呈 現(xiàn)頁面。
BackCompat:怪異模式(混雜模式)(Quick mode),瀏覽器使用自己的 怪異模式解析渲染頁面。在怪異模式中,頁面以一種比較寬松的向后 兼容的方式顯示。
如果沒有 defer 或 async 屬性,瀏覽器會(huì)立即加載并執(zhí)行相應(yīng)的腳本。它不會(huì)等待后續(xù)加載的文檔元素,讀取到就會(huì)開始加載和執(zhí)行,這樣 就阻塞了后續(xù)文檔的加載。
下圖可以直觀地看出三者之間的區(qū)別:
其中藍(lán)色代表 js 腳本網(wǎng)絡(luò)加載時(shí)間,紅色代表 js 腳本執(zhí)行時(shí)間,綠 色代表 html 解析。
defer 和 async 屬性都是去異步加載外部的 JS 腳本文件,它們都不 會(huì)阻塞頁面的解析,其區(qū)別如下:
執(zhí)行順序:多個(gè)帶 async 屬性的標(biāo)簽,不能保證加載的順序;多個(gè)帶 defer 屬性的標(biāo)簽,按照加載順序執(zhí)行;
腳本是否并行執(zhí)行:async 屬性,表示后續(xù)文檔的加載和執(zhí)行與 js 腳本的加載和執(zhí)行是并行進(jìn)行的,即異步執(zhí)行;defer 屬性,加載后 續(xù)文檔的過程和 js 腳本的加載(此時(shí)僅加載不執(zhí)行)是并行進(jìn)行的(異步),js 腳本需要等到文檔所有元素解析完成之后才執(zhí)行,DOMContentLoaded 事件觸發(fā)執(zhí)行之前。
行內(nèi)元素有:a b span img input select strong;
塊級(jí)元素有:div ul ol li dl dt dd h1 h2 h3 h4 h5 h6 p;
空元素,即沒有內(nèi)容的 HTML 元素??赵厥窃陂_始標(biāo)簽中關(guān)閉的,也就是空元素沒有閉合標(biāo)簽:
常見的有:<br>、<hr>、<img>、<input>、<link>、<meta>;
鮮見的有:<area>、<base>、<col>、<colgroup>、<command>、<embed>、<keygen>、<param>、<source>、<track>、<wbr>。
在線的情況下,瀏覽器發(fā)現(xiàn) html 頭部有 manifest 屬性,它會(huì)請(qǐng)求 manifest 文件,如果是第一次訪問頁面 ,那么瀏覽器就會(huì)根據(jù) manifest 文件的內(nèi)容下載相應(yīng)的資源并且進(jìn)行離線存儲(chǔ)。如果已經(jīng) 訪問過頁面并且資源已經(jīng)進(jìn)行離線存儲(chǔ)了,那么瀏覽器就會(huì)使用離線 的資源加載頁面,然后瀏覽器會(huì)對(duì)比新的 manifest 文件與舊的 manifest 文件,如果文件沒有發(fā)生改變,就不做任何操作,如果文 件改變了,就會(huì)重新下載文件中的資源并進(jìn)行離線存儲(chǔ)。
離線的情況下,瀏覽器會(huì)直接使用離線存儲(chǔ)的資源。
(1)SVG:
SVG 可縮放矢量圖形(Scalable Vector Graphics)是基于可擴(kuò)展標(biāo) 記語言 XML 描述的 2D 圖形的語言,SVG 基于 XML 就意味著 SVG DOM 中的每個(gè)元素都是可用的,可以為某個(gè)元素附加 Javascript 事件處 理器。在 SVG 中,每個(gè)被繪制的圖形均被視為對(duì)象。如果 SVG 對(duì)象 的屬性發(fā)生變化,那么瀏覽器能夠自動(dòng)重現(xiàn)圖形。
其特點(diǎn)如下:
不依賴分辨率
支持事件處理器
最適合帶有大型渲染區(qū)域的應(yīng)用程序(比如谷歌地圖)
復(fù)雜度高會(huì)減慢渲染速度(任何過度使用 DOM 的應(yīng)用都不快)不適合游戲應(yīng)用
(2)Canvas:
Canvas 是畫布,通過 Javascript 來繪制 2D 圖形,是逐像素進(jìn)行渲 染的。其位置發(fā)生改變,就會(huì)重新進(jìn)行繪制。
其特點(diǎn)如下:
依賴分辨率
不支持事件處理器
弱的文本渲染能力
能夠以 .png 或 .jpg 格式保存結(jié)果圖像
最適合圖像密集型的游戲,其中的許多對(duì)象會(huì)被頻繁重繪
注:矢量圖,也稱為面向?qū)ο蟮膱D像或繪圖圖像,在數(shù)學(xué)上定義為一 系列由線連接的點(diǎn)。矢量文件中的圖形元素稱為對(duì)象。每個(gè)對(duì)象都是
一個(gè)自成一體的實(shí)體,它具有顏色、形狀、輪廓、大小和屏幕位置等 屬性。
dragstart:事件主體是被拖放元素,在開始拖放被拖放元素時(shí)觸發(fā)。
darg:事件主體是被拖放元素,在正在拖放被拖放元素時(shí)觸發(fā)。dragenter:事件主體是目標(biāo)元素,在被拖放元素進(jìn)入某元素時(shí)觸發(fā)。dragover:事件主體是目標(biāo)元素,在被拖放在某元素內(nèi)移動(dòng)時(shí)觸發(fā)。dragleave:事件主體是目標(biāo)元素,在被拖放元素移出目標(biāo)元素是觸 發(fā)。
drop:事件主體是目標(biāo)元素,在目標(biāo)元素完全接受被拖放元素時(shí)觸發(fā)。
dragend:事件主體是被拖放元素,在整個(gè)拖放操作結(jié)束時(shí)觸發(fā)。
三部分 附錄(因?yàn)闀簳r(shí)不支持插入超鏈接所以部分內(nèi)容無法顯示)
附錄一 DIV命名規(guī)范
附錄二 CSS精靈
a { display:block; width:200px; height:65px; line-height:65px; /*定義狀態(tài)*/ text-indent:-2015px; /*隱藏文字*/ background-image:url(button.png); /*定義背景圖片*/ background-position:0 0; /*定義鏈接的普通狀態(tài),此時(shí)圖像顯示的是頂上的部分*/ } a:hover { background-position:0 -66px; /*定義鏈接的滑過狀態(tài),此時(shí)顯示的為中間部分,向下取負(fù)值*/ } a:active { background-position:0 -132px; /*定 義鏈接的普通狀態(tài),此時(shí)顯示的是底部的部分,向下取負(fù)值*/ }
附錄三 一些tips解決方案
頁面優(yōu)化實(shí)踐
寫DIV+CSS 的一些常識(shí)
常用代碼片段
body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td { margin:0; padding:0; } body { background:#fff; color:#555; font-size:14px; font-family: Verdana, Arial, Helvetica, sans-serif; } td, th, caption { font-size:14px; } h1, h2, h3, h4, h5, h6 { font-weight:normal; font-size:100%; } address, caption, cite, code, dfn, em, strong, th, var { font-style:normal; font-weight:normal; } a { color:#555; text-decoration:none; } a:hover { text-decoration:underline; } img { border:none; } ol,ul,li { list-style:none; } input, textarea, select, button { font:14px Verdana,Helvetica,Arial,sans-serif; } table { border-collapse:collapse; } html { overflow-y: scroll; } .clearfix:after { content: "."; display: block; height:0; clear:both; visibility: hidden; } .clearfix { *zoom:1; }
<meta name=”viewport” content=”width=320,target-densitydpi=dpi_value,initial-scale=1, user-scalable=no”/>
table-layout: fixed; word-break: break-all;;border-collapse: collapse
<div id=”abc” style=”display:table;text-align:center;width:100%;height:100%;”> <span style=”background:#f00; display:table-cell; vertical-align:middle;”> <input type=”button” value=”item1″ /> </span> </div>
filter:alpha(opacity=50); /*1-100*/ -moz-opacity:0.5; /*0-1.0*/ -khtml-opacity:0.5; /*0-1.0*/ opacity:0.5; /*0-1.0*/
white-space:nowrap; text-overflow:ellipsis; overflow:hidden;
.fix{zoom:1;} .fix:after{ display:block; content:'clear'; clear:both; line-height:0; visibility:hidden; }
一些總結(jié)
一些概念
學(xué)習(xí)從來不是一個(gè)人的事情,要有個(gè)相互監(jiān)督的伙伴,想要學(xué)習(xí)或交流前端問題的小伙伴可以私信“學(xué)習(xí)”小明加群獲取2019web前端最新入門資料,一起學(xué)習(xí),一起成長!
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。