從「從輸入U(xiǎn)RL到頁(yè)面加載」談及Web性能優(yōu)化

如何理解 Web 性能優(yōu)化

事實(shí)上就是用戶覺(jué)得頁(yè)面加載很快誉裆,用戶從輸入U(xiǎn)RL(網(wǎng)址)到頁(yè)面在瀏覽器上加載出來(lái)的時(shí)間很短黑竞;與之相對(duì)的有如服務(wù)器性能優(yōu)化(如網(wǎng)頁(yè)占的 CPU 少)休里,一定要區(qū)分開來(lái)澄干。
對(duì)于用戶眾多的網(wǎng)站,節(jié)約下的加載時(shí)間或能帶來(lái)可觀的收入罐柳,這便是前端 Web 性能優(yōu)化的意義锻狗。

從輸入 URL 到頁(yè)面加載發(fā)生了什么

一道所有前端耳熟能詳?shù)慕?jīng)典面試題满力,也確實(shí)是需要前端去深入研究的東西。下面我會(huì)簡(jiǎn)單介紹其過(guò)程轻纪,并羅列相關(guān)的 Web 優(yōu)化方案油额。

0. 緩存

當(dāng)我們?cè)跒g覽器上輸入網(wǎng)址,瀏覽器首先會(huì)查看是否有緩存刻帚,如果之前已經(jīng)訪問(wèn)過(guò)該網(wǎng)站潦嘶,則會(huì)有緩存,那瀏覽器就不必再向服務(wù)器發(fā)請(qǐng)求了崇众,用戶則能夠很快得看到內(nèi)容掂僵。Web 性能優(yōu)化有極大一部分都是優(yōu)化緩存,緩存事實(shí)上又分為數(shù)據(jù)庫(kù)緩存顷歌、代理服務(wù)器緩存锰蓬、還有我們熟悉的 CDN 緩存,以及瀏覽器緩存等眯漩,部分內(nèi)容后文介紹芹扭。

1. DNS 查詢

DNS 查詢就像電話簿,你在瀏覽器地址欄輸入網(wǎng)址赦抖,通過(guò) DNS 查詢得到域名的真實(shí) IP舱卡。

DNS查詢完成之前,瀏覽器無(wú)法從服務(wù)器下載任何數(shù)據(jù)队萤。

優(yōu)化方案:減少 DNS 查詢

1.1 DNS 緩存

ISP轮锥、局域網(wǎng)、操作系統(tǒng)要尔、瀏覽器等都會(huì)有相應(yīng)的DNS緩存機(jī)制交胚。

1.2 減少頁(yè)面的唯一域名

因?yàn)槊看?DNS 查詢就是查找唯一域名的過(guò)程,那么域名越少盈电,DNS 查詢就越少,應(yīng)該盡量將資源放在同一域名杯活。當(dāng)然這樣做又有其他問(wèn)題匆帚,下文詳解。

2. TCP 連接

經(jīng)典的三次握手和四次揮手旁钧,不展開贅述吸重。
簡(jiǎn)單講講優(yōu)化方案:TCP 連接復(fù)用(TCP Connection Reuse)互拾,在 HTTP 請(qǐng)求頭中的 Connection 上加 keep-alive;HTTP/2.0 多路復(fù)用等嚎幸。

3. HTTP 請(qǐng)求及響應(yīng)

直接講優(yōu)化策略

3.1 避免不必要的重定向

最浪費(fèi)的重定向經(jīng)常發(fā)生颜矿、而且很容易被忽略:URL 末尾應(yīng)該添加/但未添加。比如嫉晶,訪問(wèn)http://astrology.yahoo.com/astrology將被301重定向到 http://astrology.yahoo.com/astrology/(注意末尾的 /)骑疆。如果使用 Apache,可以通過(guò)Alias或mod_rewrite或DirectorySlash解決這個(gè)問(wèn)題替废。

3.2 Cookie

3.2.1減少 Cookie 大小

每次請(qǐng)求都會(huì)帶上對(duì)應(yīng)的 Cookie箍铭,減少 Cookie 大小可以降低其對(duì)響應(yīng)速度的影響:

  • 去除不必要的 Cookie;
  • 盡量壓縮 Cookie 大凶盗汀诈火;
  • 注意設(shè)置 Cookie 的 domain 級(jí)別,如無(wú)必要状答,不要影響到 sub-domain冷守;
  • 設(shè)置合適的過(guò)期時(shí)間。
3.2.2 靜態(tài)資源使用無(wú) Cookie 域名

靜態(tài)資源一般無(wú)需使用 Cookie惊科,可以把它們放在使用二級(jí)域名或者專門域名的無(wú) Cookie 服務(wù)器上拍摇,降低 Cookie 傳送的造成的流量浪費(fèi),提高響應(yīng)速度译断。

3.3 添加 Expires 或 Cache-Control 響應(yīng)頭

HTTP/1.1 增加的 Cache-Control授翻,它比 Expires 等好在其設(shè)定時(shí)間是相對(duì)的,避免了用戶本地設(shè)置時(shí)間落后所造成的無(wú)法良好緩存的問(wèn)題等孙咪。

  • 靜態(tài)內(nèi)容:將 Expires 響應(yīng)頭設(shè)置為將來(lái)很遠(yuǎn)的時(shí)間堪唐,實(shí)現(xiàn)「永不過(guò)期」策略;
  • 動(dòng)態(tài)內(nèi)容:設(shè)置合適的 Cache-Control 響應(yīng)頭翎蹈,讓瀏覽器有條件地發(fā)起請(qǐng)求淮菠。

3.4 配置 Etag

通過(guò)如 MD5 等加密算法,設(shè)置緩存體的 Etag 配合 3.3 的緩存時(shí)間使用荤堪,這樣 Cache-Control 就可以設(shè)置較長(zhǎng)時(shí)間(max-age 設(shè)置個(gè)十年半載 )合陵,只要瀏覽器緩存中資源與源服務(wù)器中的資源 Etag 不一致,說(shuō)明內(nèi)容更新了澄阳,此時(shí)再下載新資源拥知;Etag 匹配成功則直接響應(yīng) 304,不用重復(fù)下載了用戶自然感覺(jué)很快碎赢。

3.5 使用 Gzip

使用 Gzip 就是將 HTML低剔、CSS、JS、XML襟齿、JSON 等資源進(jìn)行 Gzip 高效壓縮姻锁,減少資源體積那么下載就會(huì)更快。
Gzip 壓縮通巢缕郏可以減少 70% 的響應(yīng)大小位隶,對(duì)某些文件更可能高達(dá) 90%,比 Deflate 更高效开皿。主流 Web 服務(wù)器都有相應(yīng)模塊涧黄,而且絕大多數(shù)瀏覽器支持 Gzip 解碼。
從HTTP/1.1開始副瀑,客戶端就有了支持壓縮的 Accept-Encoding HTTP 請(qǐng)求頭弓熏。

Accept-Encoding: gzip, deflate

服務(wù)器看到這個(gè)請(qǐng)求頭,它就會(huì)用客戶端列出的一種方式來(lái)壓縮響應(yīng)糠睡。web服務(wù)器通過(guò) Content-Encoding 響應(yīng)頭來(lái)通知客戶端挽鞠。

Content-Encoding: gzip

需要注意的是,已經(jīng)壓縮過(guò)的內(nèi)容如圖片和PDF不要使用 Gzip狈孔,另外還有文件內(nèi)容本身就很小信认,這些資源再使用 Gzip 反而會(huì)增加資源下載時(shí)間,浪費(fèi) CPU 資源均抽,而且還可能增加文件體積嫁赏。

值得一提

HTTP 請(qǐng)求的另一個(gè)優(yōu)化方案是增加同時(shí)請(qǐng)求的數(shù)量,瀏覽器會(huì)同時(shí)發(fā)送多個(gè)請(qǐng)求油挥,但是同一域名最多同時(shí)發(fā)送 4~8 個(gè)(不同瀏覽器不同)請(qǐng)求潦蝇,那么當(dāng)資源過(guò)多時(shí),可以采用增加域名的方法增加并發(fā)量深寥。當(dāng)然這一方法又與上述 DNS 查詢的優(yōu)化方案矛盾攘乒,真正使用的時(shí)候就需要權(quán)衡。
另外惋鹅,既然一次只能發(fā)的請(qǐng)求有限则酝,就應(yīng)該將重要的需要優(yōu)先展示的資源先請(qǐng)求:

3.6 延遲加載(懶加載)

頁(yè)面初始加載時(shí)哪些內(nèi)容是絕對(duì)必需的?不在答案之列的資源都可以延遲加載闰集。比如:

  • 非首屏使用的數(shù)據(jù)沽讹、樣式、腳本武鲁、圖片等爽雄;
  • 用戶交互時(shí)才會(huì)顯示的內(nèi)容。

遵循「漸進(jìn)增強(qiáng)」理念開發(fā)的網(wǎng)站:JavaScript用于增強(qiáng)用用戶體驗(yàn)沐鼠,但沒(méi)有(不支持) JavaScript也能正常工作盲链,完全可以延遲加載JavaScript。

將首屏以外的HTML放在不渲染的元素中,如隱藏的<textarea>刽沾,或者type屬性為非執(zhí)行腳本的<script>標(biāo)簽中,減少初始渲染的DOM元素?cái)?shù)量排拷,提高速度侧漓。等首屏加載完成或者用戶操作時(shí),再去渲染剩余的頁(yè)面內(nèi)容监氢。

3.7 預(yù)加載

預(yù)先加載利用瀏覽器空閑時(shí)間請(qǐng)求將來(lái)要使用的資源布蔗,以便用戶訪問(wèn)下一頁(yè)面時(shí)更快地響應(yīng)。

4. 瀏覽器解析渲染頁(yè)面

響應(yīng)完成后浪腐,瀏覽器下載完資源纵揍,就開始解析資源生成頁(yè)面了。對(duì)于前端來(lái)說(shuō)议街,這部分內(nèi)容是完全需要我們?nèi)フ瓶氐脑蠼鳎覀円瞾?lái)簡(jiǎn)單介紹一下對(duì)應(yīng)的優(yōu)化內(nèi)容,部分內(nèi)容如懶加載等上面已經(jīng)提及就不再重復(fù)特漩。

4.1 寫對(duì)文檔類型聲明 <!DOCTYPE html>

這個(gè)聲明的目的是防止瀏覽器在渲染文檔時(shí)吧雹,切換到我們稱為“怪異模式(兼容模式)”的渲染模式⊥可恚“<!DOCTYPE html>" 確保瀏覽器按照最佳的相關(guān)規(guī)范進(jìn)行渲染雄卷,而不是使用一個(gè)不符合規(guī)范的渲染模式。

不寫或?qū)戝e(cuò)文檔類型聲明蛤售,會(huì)浪費(fèi)瀏覽器渲染頁(yè)面的時(shí)間或引起錯(cuò)誤排版丁鹉。

4.2 CSS 放在 <head> 中

把樣式表放在 <head> 中可以讓頁(yè)面漸進(jìn)渲染,盡早呈現(xiàn)視覺(jué)反饋悴能,給用戶加載速度很快的感覺(jué)揣钦。
這對(duì)內(nèi)容比較多的頁(yè)面尤為重要,用戶可以先查看已經(jīng)下載渲染的內(nèi)容搜骡,而不是盯著白屏等待拂盯。
如果把樣式表放在頁(yè)面底部,一些瀏覽器為減少重繪记靡,會(huì)在 CSS 加載完成以后才渲染頁(yè)面谈竿,用戶只能對(duì)著白屏干瞪眼,用戶體驗(yàn)極差摸吠。把樣式表放到文檔的HEAD部分能讓頁(yè)面看起來(lái)加載地更快空凸。

4.2 把腳本放在頁(yè)面底部

瀏覽器下載腳本時(shí),會(huì)阻塞其他資源并行下載寸痢,即使是來(lái)自不同域名的資源呀洲,并且,沒(méi)有 js 并不郵箱呈現(xiàn)在用戶目前的內(nèi)容的觀感。因此道逗,最好將腳本放在底部兵罢,以提高頁(yè)面加載速度。
一些特殊場(chǎng)景無(wú)法將腳本放到頁(yè)面底部的滓窍,可以考慮<script>的以下屬性:

  • defer 屬性卖词;
  • HTML5 新增的async屬性。

4.3 使用外部 JavaScript 和 CSS

外部 JavaScript 和 CSS 文件可以被瀏覽器緩存吏夯,在不同頁(yè)面間重用此蜈,也能降低頁(yè)面大小。
當(dāng)然噪生,實(shí)際中也需要考慮代碼的重用程度裆赵。如果僅僅是某個(gè)頁(yè)面使用到的代碼,可以考慮內(nèi)嵌在頁(yè)面中跺嗽,減少HTTP請(qǐng)求數(shù)战授。另外,可以在首頁(yè)加載完成以后抛蚁,預(yù)先加載子頁(yè)面的資源陈醒。

4.4 合并和壓縮 JS/CSS 等文件

通過(guò)該方法減少頁(yè)面所需資源,減少請(qǐng)求數(shù)量瞧甩,加快響應(yīng)時(shí)間《危現(xiàn)在 webpack 打包工具都已經(jīng)默認(rèn)實(shí)現(xiàn)了。

4.5 減少 DOM 操作和使用高效的事件處理

  • 緩存已經(jīng)訪問(wèn)過(guò)的元素肚逸;
  • 使用 DocumentFragment 暫存 DOM爷辙,整理好以后再插入 DOM 樹;
  • 操作 className朦促,而不是多次讀寫 style膝晾;
  • 避免使用 JavaScript 修復(fù)布局;
  • 減少綁定事件監(jiān)聽(tīng)的節(jié)點(diǎn)务冕,如通過(guò)事件委托(當(dāng)然現(xiàn)在瀏覽器功能強(qiáng)大血当,影響不大);
  • 盡早處理事件禀忆,在 DOMContentLoaded 即可進(jìn)行臊旭,不用等到 load 以后。

4.6 圖片優(yōu)化

如何將圖片變得又小又好看是一個(gè)工程師實(shí)力的體現(xiàn)箩退,這里不過(guò)多贅述离熏,大家可以查看我后文提供的資源。

4.7 使用 CND

內(nèi)容分發(fā)網(wǎng)絡(luò)(Content delivery network 或 Content distribution network)是指一種透過(guò)互聯(lián)網(wǎng)互相連接的計(jì)算機(jī)網(wǎng)絡(luò)系統(tǒng)戴涝,利用最靠近每位用戶的服務(wù)器滋戳,更快钻蔑、更可靠地將音樂(lè)、圖片奸鸯、影片咪笑、應(yīng)用程序及其他文件發(fā)送給用戶,來(lái)提供高性能娄涩、可擴(kuò)展性及低成本的網(wǎng)絡(luò)內(nèi)容傳遞給用戶蒲肋。

動(dòng)態(tài) CDN,使用離你最近的服務(wù)器钝满;CDN 沒(méi)有 Cookie,使用 CDN 可以減少 Cookie申窘;CND 會(huì)自動(dòng)合并腳本文件等弯蚜,減少請(qǐng)求數(shù)量;當(dāng)然剃法,使用 CND 同時(shí)也增加了一個(gè)域名碎捺,增大了同時(shí)請(qǐng)求數(shù)量。

總結(jié)


該文大量參考了雅虎 35 軍規(guī)贷洲,增加了一些自己的理解并舍棄了一些已經(jīng)過(guò)時(shí)的內(nèi)容收厨。細(xì)節(jié)內(nèi)容比較少,主要是籠統(tǒng)地將 Web 性能優(yōu)化的思路做了梳理优构,很多內(nèi)容都值得我們?nèi)ド钊胙芯克腥.?dāng)然其中部分內(nèi)容順序還是不佳,因?yàn)楹芏鄡?nèi)容事實(shí)上是貫穿在整個(gè)過(guò)程當(dāng)中的钦椭,正如 Web 性能優(yōu)化是個(gè)整體拧额,需要權(quán)衡所有沖突。希望本文可以給你一些在面試官問(wèn)道你時(shí)的思路彪腔。
深入閱讀 從輸入U(xiǎn)RL到頁(yè)面加載的過(guò)程侥锦?如何由一道題完善自己的前端知識(shí)體系!

本文參考:
前端性能優(yōu)化之雅虎35條軍規(guī)
前端經(jīng)典面試題: 從輸入U(xiǎn)RL到頁(yè)面加載發(fā)生了什么德挣?
MDN
維基百科

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末恭垦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子格嗅,更是在濱河造成了極大的恐慌番挺,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吗浩,死亡現(xiàn)場(chǎng)離奇詭異建芙,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)懂扼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門禁荸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)右蒲,“玉大人,你說(shuō)我怎么就攤上這事赶熟」逋” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵映砖,是天一觀的道長(zhǎng)间坐。 經(jīng)常有香客問(wèn)我,道長(zhǎng)邑退,這世上最難降的妖魔是什么竹宋? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮地技,結(jié)果婚禮上蜈七,老公的妹妹穿的比我還像新娘。我一直安慰自己莫矗,他們只是感情好飒硅,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著作谚,像睡著了一般三娩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上妹懒,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天雀监,我揣著相機(jī)與錄音,去河邊找鬼彬伦。 笑死滔悉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的单绑。 我是一名探鬼主播回官,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼搂橙!你這毒婦竟也來(lái)了歉提?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤区转,失蹤者是張志新(化名)和其女友劉穎苔巨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體废离,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侄泽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蜻韭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悼尾。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柿扣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出闺魏,到底是詐尸還是另有隱情未状,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布析桥,位于F島的核電站司草,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏泡仗。R本人自食惡果不足惜埋虹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望娩怎。 院中可真熱鬧吨岭,春花似錦、人聲如沸峦树。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)魁巩。三九已至,卻和暖如春姐浮,著一層夾襖步出監(jiān)牢的瞬間谷遂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工卖鲤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肾扰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓蛋逾,卻偏偏與公主長(zhǎng)得像集晚,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子区匣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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