1. 知識(shí)體系 1.1從輸入 URL 到頁(yè)面加載完成,發(fā)生了什么?
首先我們需要通過 DNS(域名解析系統(tǒng))將 URL 解析為對(duì)應(yīng)的 IP 地址,然后與這個(gè) IP 地址確定的那臺(tái)服務(wù)器建立起 TCP 網(wǎng)絡(luò)連接,隨后我們向服務(wù)端拋出我們的 HTTP 請(qǐng)求,服務(wù)端處理完我們的請(qǐng)求之后,把目標(biāo)數(shù)據(jù)放在 HTTP 響應(yīng)里返回給客戶端,拿到響應(yīng)數(shù)據(jù)的瀏覽器就可以開始走一個(gè)渲染的流程。渲染完畢,頁(yè)面便呈現(xiàn)給了用戶
將這個(gè)過程切分為如下的過程片段
DNS 解析
TCP 連接
HTTP 請(qǐng)求拋出
服務(wù)端處理請(qǐng)求,HTTP 響應(yīng)返回
瀏覽器拿到響應(yīng)數(shù)據(jù),解析響應(yīng)內(nèi)容,把解析的結(jié)果展示給用戶
1.2性能優(yōu)化思維導(dǎo)圖 2.網(wǎng)絡(luò)篇(http) 2.1 前端能做的網(wǎng)絡(luò)優(yōu)化輸入 URL 到顯示頁(yè)面這個(gè)過程中,涉及到網(wǎng)絡(luò)層面的,有三個(gè)主要過程:
DNS 解析
TCP 連接
HTTP 請(qǐng)求/響應(yīng)
對(duì)于 DNS 解析和 TCP 連接兩個(gè)步驟,我們前端可以做的努力非常有限。相比之下,HTTP 連接這一層面的優(yōu)化才是我們網(wǎng)絡(luò)優(yōu)化的核心
HTTP 優(yōu)化有兩個(gè)大的方向
減少請(qǐng)求次數(shù)
減少單次請(qǐng)求所花費(fèi)的時(shí)間
2.1 減少請(qǐng)求次數(shù) 2.1.1 圖片:雪碧圖,圖標(biāo)字體文件雪碧圖
多張小圖片合并為一張圖,利用CSS -background-position調(diào)整圖片顯示位置
圖標(biāo)字體文件
阿里圖標(biāo)
2.1.2 合并JS和CSS文件webpack,需要斟酌而定
2.1.3 瀏覽器緩存如果圖片或者腳本,樣式文件內(nèi)容比較固定,不經(jīng)常被修改,那么,盡可能利用緩存技術(shù),減少HTTP請(qǐng)求次數(shù)或文件下載次數(shù)
2.2 減少單次請(qǐng)求所花費(fèi)的時(shí)間主要是減少請(qǐng)求中數(shù)據(jù)的大小,從而達(dá)到減少單次請(qǐng)求所花費(fèi)的時(shí)間
2.2.1 圖片圖片在線批量壓縮
gzip如果是vue項(xiàng)目,還有nginx,哪么vue,nginx,服務(wù)器都要開啟gzip
3.網(wǎng)絡(luò)篇(圖片優(yōu)化) 3.1不同業(yè)務(wù)場(chǎng)景下的圖片方案選型 3.1.1前置知識(shí):二進(jìn)制位數(shù)與色彩的關(guān)系在計(jì)算機(jī)中,像素用二進(jìn)制數(shù)來表示。不同的圖片格式中像素與二進(jìn)制位數(shù)之間的對(duì)應(yīng)關(guān)系是不同的。一個(gè)像素對(duì)應(yīng)的二進(jìn)制位數(shù)越多,它可以表示的顏色種類就越多,成像效果也就越細(xì)膩,文件體積相應(yīng)也會(huì)越大。
3.2 JPEG/JPG關(guān)鍵字:有損壓縮、體積小、加載快、不支持透明
3.2.1 JPG 的優(yōu)點(diǎn)JPG 最大的特點(diǎn)是有損壓縮。這種高效的壓縮算法使它成為了一種非常輕巧的圖片格式。另一方面,即使被稱為“有損”壓縮,JPG的壓縮方式仍然是一種高質(zhì)量的壓縮方式:當(dāng)我們把圖片體積壓縮至原有體積的 50% 以下時(shí),JPG 仍然可以保持住 60% 的品質(zhì)。此外,JPG 格式以 24 位存儲(chǔ)單個(gè)圖,可以呈現(xiàn)多達(dá) 1600 萬種顏色,足以應(yīng)對(duì)大多數(shù)場(chǎng)景下對(duì)色彩的要求,這一點(diǎn)決定了它壓縮前后的質(zhì)量損耗并不容易被我們?nèi)祟惖娜庋鬯煊X——前提是你用對(duì)了業(yè)務(wù)場(chǎng)景。
3.2.2 使用場(chǎng)景JPG 適用于呈現(xiàn)色彩豐富的圖片,在我們?nèi)粘i_發(fā)中,JPG 圖片經(jīng)常作為大的背景圖、輪播圖或 Banner 圖出現(xiàn)。
兩大電商網(wǎng)站對(duì)大圖的處理,是 JPG 圖片應(yīng)用場(chǎng)景的最佳寫照:
打開淘寶首頁(yè),我們可以發(fā)現(xiàn)頁(yè)面中最醒目、最龐大的圖片,一定是以 .jpg 為后綴的:
使用 JPG 呈現(xiàn)大圖,既可以保住圖片的質(zhì)量,又不會(huì)帶來令人頭疼的圖片體積,是當(dāng)下比較推崇的一種方案。
3.2.3 JPG 的缺陷有損壓縮在上文所展示的輪播圖上確實(shí)很難露出馬腳,但當(dāng)它處理矢量圖形和 Logo 等線條感較強(qiáng)、顏色對(duì)比強(qiáng)烈的圖像時(shí),人為壓縮導(dǎo)致的圖片模糊會(huì)相當(dāng)明顯。
此外,JPEG 圖像不支持透明度處理,透明圖片需要召喚 PNG 來呈現(xiàn)。
關(guān)鍵字:無損壓縮、質(zhì)量高、體積大、支持透明
3.3.1 PNG 的優(yōu)點(diǎn)PNG(可移植網(wǎng)絡(luò)圖形格式)是一種無損壓縮的高保真的圖片格式。8 和 24,這里都是二進(jìn)制數(shù)的位數(shù)。按照我們前置知識(shí)里提到的對(duì)應(yīng)關(guān)系,8 位的 PNG 最多支持 256 種顏色,而 24 位的可以呈現(xiàn)約 1600 萬種顏色。
PNG 圖片具有比 JPG 更強(qiáng)的色彩表現(xiàn)力,對(duì)線條的處理更加細(xì)膩,對(duì)透明度有良好的支持。它彌補(bǔ)了上文我們提到的 JPG 的局限性,唯一的 BUG 就是體積太大。
3.3.2PNG-8 與 PNG-24 的選擇題什么時(shí)候用 PNG-8,什么時(shí)候用 PNG-24,這是一個(gè)問題
理論上來說,當(dāng)你追求最佳的顯示效果、并且不在意文件體積大小時(shí),是推薦使用 PNG-24 的。
但實(shí)踐當(dāng)中,為了規(guī)避體積的問題,我們一般不用PNG去處理較復(fù)雜的圖像。當(dāng)我們遇到適合 PNG 的場(chǎng)景時(shí),也會(huì)優(yōu)先選擇更為小巧的 PNG-8。
如何確定一張圖片是該用 PNG-8 還是 PNG-24 去呈現(xiàn)呢?好的做法是把圖片先按照這兩種格式分別輸出,看 PNG-8 輸出的結(jié)果是否會(huì)帶來肉眼可見的質(zhì)量損耗,并且確認(rèn)這種損耗是否在我們(尤其是你的 UI 設(shè)計(jì)師)可接受的范圍內(nèi),基于對(duì)比的結(jié)果去做判斷。
3.3.3 應(yīng)用場(chǎng)景前面我們提到,復(fù)雜的、色彩層次豐富的圖片,用 PNG 來處理的話,成本會(huì)比較高,我們一般會(huì)交給 JPG 去存儲(chǔ)。
考慮到 PNG 在處理線條和顏色對(duì)比度方面的優(yōu)勢(shì),我們主要用它來呈現(xiàn)小的 Logo、顏色簡(jiǎn)單且對(duì)比強(qiáng)烈的圖片或背景等。
此時(shí)我們?cè)俅伟涯抗廪D(zhuǎn)向性能方面堪稱業(yè)界楷模的淘寶首頁(yè),我們會(huì)發(fā)現(xiàn)它頁(yè)面上的 Logo,無論大小,還真的都是 PNG 格式:
3.4 SVG關(guān)鍵字:文本文件、體積小、不失真、兼容性好
3.4.1 SVG 的使用方式與應(yīng)用場(chǎng)景將 SVG 寫入 HTML
將 SVG 寫入獨(dú)立文件后引入 HTML:
3.5 Base64關(guān)鍵字:文本文件、依賴編碼、小圖標(biāo)解決方案
3.5.1 Base64 的應(yīng)用場(chǎng)景圖片的實(shí)際尺寸很?。ù蠹铱梢杂^察一下掘金頁(yè)面的 Base64 圖,幾乎沒有超過 2kb 的)
圖片無法以雪碧圖的形式與其它小圖結(jié)合(合成雪碧圖仍是主要的減少 HTTP 請(qǐng)求的途徑,Base64 是雪碧圖的補(bǔ)充)
圖片的更新頻率非常低(不需我們重復(fù)編碼和修改文件內(nèi)容,維護(hù)成本較低)
3.6 WebP關(guān)鍵字:年輕的全能型選手
是 Google 專為 Web 開發(fā)的一種旨在加快圖片加載速度的圖片格式,它支持有損壓縮和無損壓縮。
WebP 像 JPEG 一樣對(duì)細(xì)節(jié)豐富的圖片信手拈來,像 PNG 一樣支持透明,像 GIF 一樣可以顯示動(dòng)態(tài)圖片——它集多種圖片文件格式的優(yōu)點(diǎn)于一身。
3.6.2WebP 的局限性兼容性
3.7 總結(jié)不同業(yè)務(wù)場(chǎng)景下的圖片方案選型
4.存儲(chǔ)篇(瀏覽器緩存) 4.1 什么是緩存對(duì)于一個(gè)數(shù)據(jù)請(qǐng)求來說,可以分為發(fā)起網(wǎng)絡(luò)請(qǐng)求、后端處理、瀏覽器響應(yīng)三個(gè)步驟
瀏覽器緩存可以幫助我們?cè)诘谝缓偷谌襟E中優(yōu)化性能。比如說直接使用緩存而不發(fā)起請(qǐng)求,或者發(fā)起了請(qǐng)求但后端存儲(chǔ)的數(shù)據(jù)和前端一致,那么就沒有必要再將數(shù)據(jù)回傳回來,這樣就減少了響應(yīng)數(shù)據(jù)。
緩存思維導(dǎo)圖
4.2 緩存位置 4.2.1 緩存優(yōu)先級(jí)從緩存位置上來說分為四種,并且各自有優(yōu)先級(jí),當(dāng)依次查找緩存且都沒有命中的時(shí)候,才會(huì)去請(qǐng)求網(wǎng)絡(luò)。
Service Worker
Memory Cache
Disk Cache
Push Cache
4.2.2 Service Worker不了解
MDN
MemoryCache,是指存在內(nèi)存中的緩存。從優(yōu)先級(jí)上來說,它是瀏覽器最先嘗試去命中的一種緩存。從效率上來說,它是響應(yīng)速度最快的一種緩存。
內(nèi)存緩存是快的,也是“短命”的。它和渲染進(jìn)程“生死相依”,當(dāng)進(jìn)程結(jié)束后,也就是 tab 關(guān)閉以后,內(nèi)存里的數(shù)據(jù)也將不復(fù)存在。
那么哪些文件會(huì)被放入內(nèi)存呢?
事實(shí)上,這個(gè)劃分規(guī)則,一直以來是沒有定論的。不過想想也可以理解,內(nèi)存是有限的,很多時(shí)候需要先考慮即時(shí)呈現(xiàn)的內(nèi)存余量,再根據(jù)具體的情況決定分配給內(nèi)存和磁盤的資源量的比重——資源存放的位置具有一定的隨機(jī)性
雖然劃分規(guī)則沒有定論,但根據(jù)日常開發(fā)中觀察的結(jié)果,包括我們開篇給大家展示的 Network 截圖,我們至少可以總結(jié)出這樣的規(guī)律:資源存不存內(nèi)存,瀏覽器秉承的是“節(jié)約原則”。我們發(fā)現(xiàn),Base64 格式的圖片,幾乎永遠(yuǎn)可以被塞進(jìn) memory cache,這可以視作瀏覽器為節(jié)省渲染開銷的“自保行為”;此外,體積不大的 JS、CSS 文件,也有較大地被寫入內(nèi)存的幾率——相比之下,較大的 JS、CSS 文件就沒有這個(gè)待遇了,內(nèi)存資源是有限的,它們往往被直接甩進(jìn)磁盤。
4.2.4 Disk CacheDisk Cache 也就是存儲(chǔ)在硬盤中的緩存,讀取速度慢點(diǎn),但是什么都能存儲(chǔ)到磁盤中,比之 Memory Cache 勝在容量和存儲(chǔ)時(shí)效性上。
在所有瀏覽器緩存中,Disk Cache 覆蓋面基本是最大的。它會(huì)根據(jù) HTTP Herder 中的字段判斷哪些資源需要緩存,哪些資源可以不請(qǐng)求直接使用,哪些資源已經(jīng)過期需要重新請(qǐng)求。并且即使在跨站點(diǎn)的情況下,相同地址的資源一旦被硬盤緩存下來,就不會(huì)再次去請(qǐng)求數(shù)據(jù)。絕大部分的緩存都來自 Disk Cache,關(guān)于 HTTP 的協(xié)議頭中的緩存字段,我們會(huì)在下文進(jìn)行詳細(xì)介紹
瀏覽器會(huì)把哪些文件丟進(jìn)內(nèi)存中?哪些丟進(jìn)硬盤中
對(duì)于大文件來說,大概率是不存儲(chǔ)在內(nèi)存中的,反之優(yōu)先
當(dāng)前系統(tǒng)內(nèi)存使用率高的話,文件優(yōu)先存儲(chǔ)進(jìn)硬盤
4.2.5 Push Cache不了解
push Cache(推送緩存)是 HTTP/2 中的內(nèi)容,當(dāng)以上三種緩存都沒有命中時(shí),它才會(huì)被使用
4.3 緩存過程分析瀏覽器與服務(wù)器通信的方式為應(yīng)答模式,即是:瀏覽器發(fā)起HTTP請(qǐng)求 – 服務(wù)器響應(yīng)該請(qǐng)求,那么瀏覽器怎么確定一個(gè)資源該不該緩存,如何去緩存呢?瀏覽器第一次向服務(wù)器發(fā)起該請(qǐng)求后拿到請(qǐng)求結(jié)果后,將請(qǐng)求結(jié)果和緩存標(biāo)識(shí)存入瀏覽器緩存,瀏覽器對(duì)于緩存的處理是根據(jù)第一次請(qǐng)求資源時(shí)返回的響應(yīng)頭來確定的。具體過程如下圖:
上圖我們可以知道
瀏覽器每次發(fā)起請(qǐng)求,都會(huì)先在瀏覽器緩存中查找該請(qǐng)求的結(jié)果以及緩存標(biāo)識(shí)
瀏覽器每次拿到返回的請(qǐng)求結(jié)果都會(huì)將該結(jié)果和緩存標(biāo)識(shí)存入瀏覽器緩存中
4.4 http緩存HTTP 緩存是我們?nèi)粘i_發(fā)中最為熟悉的一種緩存機(jī)制。它又分為強(qiáng)緩存和協(xié)商緩存。優(yōu)先級(jí)較高的是強(qiáng)緩存,在命中強(qiáng)緩存失敗的情況下,才會(huì)走協(xié)商緩存。
4.5 強(qiáng)緩存強(qiáng)緩存:不會(huì)向服務(wù)器發(fā)送請(qǐng)求,直接從緩存中讀取資源,在chrome控制臺(tái)的Network選項(xiàng)中可以看到該請(qǐng)求返回200的狀態(tài)碼,并且Size顯示from disk cache或from memory cache。強(qiáng)緩存可以通過設(shè)置兩種 HTTP Header 實(shí)現(xiàn):Expires 和 Cache-Control。
4.5.1 Expires緩存過期時(shí)間,用來指定資源到期的時(shí)間,是服務(wù)器端的具體的時(shí)間點(diǎn)。也就是說,Expires=max-age + 請(qǐng)求時(shí)間,需要和Last-modified結(jié)合使用。Expires是Web服務(wù)器響應(yīng)消息頭字段,在響應(yīng)http請(qǐng)求時(shí)告訴瀏覽器在過期時(shí)間前瀏覽器可以直接從瀏覽器緩存取數(shù)據(jù),而無需再次請(qǐng)求。
Expires 是 HTTP/1 的產(chǎn)物,受限于本地時(shí)間,如果修改了本地時(shí)間,可能會(huì)造成緩存失效。Expires: Wed, 22 Oct 2018 08:41:00 GMT表示資源會(huì)在 Wed, 22 Oct 2018 08:41:00 GMT 后過期,需要再次請(qǐng)求。
緩存過期時(shí)間,用來指定資源的到期時(shí)間,是服務(wù)器端的具體的時(shí)間點(diǎn)
告訴瀏覽器在過期時(shí)間前瀏覽器可以直接從瀏覽器緩存取數(shù)據(jù),而不用再次請(qǐng)求
max-age的優(yōu)化級(jí)高于expires,當(dāng)有max-age的時(shí)候,會(huì)無視expires
當(dāng)在有效時(shí)間內(nèi),如果服務(wù)器端的文件已經(jīng)發(fā)生改變,但是瀏覽器端無法感知
4.5.2 Cache-Control在HTTP/1.1中,Cache-Control是最重要的規(guī)則,主要用于控制網(wǎng)頁(yè)緩存Cache-Control 可以在請(qǐng)求頭或者響應(yīng)頭中設(shè)置,并且可以組合使用多種指令
max-age
s-maxage
private
public
no-cache
no-store
max-age
max-age=xxx (xxx is numeric)表示緩存內(nèi)容將在xxx秒后失效
設(shè)置緩存存儲(chǔ)的最大周期,超過這個(gè)時(shí)間緩存被認(rèn)為過期(單位秒)。與Expires相反,時(shí)間是相對(duì)于請(qǐng)求的時(shí)間,
優(yōu)先級(jí)高于Expires
s-maxage
覆蓋max-age 或者 Expires 頭,但是僅適用于共享緩存(比如各個(gè)代理),并且私有緩存中它被忽略
能用于public,如CDN
優(yōu)先級(jí)高于max-age
private
所有內(nèi)容只有客戶端可以緩存
表示中間節(jié)點(diǎn)不允許緩存,對(duì)于Browser <-- proxy1 <-- proxy2 <-- Server,proxy 會(huì)老老實(shí)實(shí)把Server 返回的數(shù)據(jù)發(fā)送給proxy1,自己不緩存任何數(shù)據(jù)。當(dāng)下次Browser再次請(qǐng)求時(shí)proxy會(huì)做好請(qǐng)求轉(zhuǎn)發(fā)而不是自作主張給自己緩存的數(shù)據(jù)
表明響應(yīng)只能被單個(gè)用戶緩存,不能作為共享緩存(即代理服務(wù)器不能緩存它),可以緩存響應(yīng)內(nèi)容
自己的服務(wù)器
public
所有內(nèi)容都將被緩存(客戶端和代理服務(wù)器都可緩存)
具體來說響應(yīng)可被任何中間節(jié)點(diǎn)緩存,如 Browser <-- proxy1 <-- proxy2 <-- Server,中間的proxy可以緩存資源,比如下次再請(qǐng)求同一資源proxy1直接把自己緩存的東西給 Browser 而不再向proxy2要。
no-store
所有內(nèi)容都不會(huì)被緩存,即不使用強(qiáng)制緩存,也不使用協(xié)商緩存
緩存不應(yīng)存儲(chǔ)有關(guān)客戶端請(qǐng)求或服務(wù)器響應(yīng)的任何內(nèi)容。
不會(huì)使用任何緩存策略
no-cache
客戶端緩存內(nèi)容,是否使用緩存則需要經(jīng)過協(xié)商緩存來驗(yàn)證決定。表示不使用 Cache-Control的緩存控制方式做前置驗(yàn)證,而是使用 Etag 或者Last-Modified字段來控制緩存。需要注意的是,no-cache這個(gè)名字有一點(diǎn)誤導(dǎo)。設(shè)置了no-cache之后,并不是說瀏覽器就不再緩存數(shù)據(jù),只是瀏覽器在使用緩存數(shù)據(jù)時(shí),需要先確認(rèn)一下數(shù)據(jù)是否還跟服務(wù)器保持一致
釋放緩存副本之前,強(qiáng)制高速緩存將請(qǐng)求提交給原始服務(wù)器進(jìn)行驗(yàn)證
這個(gè)文件不管怎么樣,都會(huì)向服務(wù)器發(fā)起請(qǐng)求,去服務(wù)器哪邊詢問,這個(gè)文件有沒有在緩存策略里
強(qiáng)緩存思維導(dǎo)圖4.6 協(xié)商緩存 4.6.1 什么是協(xié)商緩存
協(xié)商緩存就是強(qiáng)制緩存失效后,瀏覽器攜帶緩存標(biāo)識(shí)向服務(wù)器發(fā)起請(qǐng)求,由服務(wù)器根據(jù)緩存標(biāo)識(shí)決定是否使用緩存的過程,主要有以下兩種情況:
協(xié)商緩存生效,返回304和Not Modified
協(xié)商緩存失效,返回200和請(qǐng)求結(jié)果4.6.2 Last-Modified和If-Modified-Since
ast-Modified 是一個(gè)響應(yīng)首部,其中包含源頭服務(wù)器認(rèn)定的資源做出修改的日期及時(shí)間。 它通常被用作一個(gè)驗(yàn)證器來判斷接收到的或者存儲(chǔ)的資源是否彼此一致。由于精確度比 ETag 要低,所以這是一個(gè)備用機(jī)制。包含有 If-Modified-Since 或 If-Unmodified-Since 首部的條件請(qǐng)求會(huì)使用這個(gè)字段。
基于客戶端和服務(wù)端協(xié)商的緩存機(jī)制
Last-Modified ----response header
If-Modified-Since----request header
需要與cache-control共同使用
max-age的優(yōu)先級(jí)高于Last-Modified
缺點(diǎn)
某些服務(wù)端不能獲取精確的修改時(shí)間
文件修改時(shí)間改了,但文件內(nèi)容卻沒有變
4.6.3 Etag/If-None-MatchETagHTTP響應(yīng)頭是資源的特定版本的標(biāo)識(shí)符。這可以讓緩存更高效,并節(jié)省帶寬,因?yàn)槿绻麅?nèi)容沒有改變,Web服務(wù)器不需要發(fā)送完整的響應(yīng)。而如果內(nèi)容發(fā)生了變化,使用ETag有助于防止資源的同時(shí)更新相互覆蓋(“空中碰撞”)
文件內(nèi)容的hash值
etag--response header
if-none-match -- request header
要與cache-control共同使用
4.6.4兩者對(duì)比首先在精確度上,Etag要優(yōu)于Last-Modified。
第二在性能上,Etag要遜于Last-Modified,畢竟Last-Modified只需要記錄時(shí)間,而Etag需要服務(wù)器通過算法來計(jì)算出一個(gè)hash值。
第三在優(yōu)先級(jí)上,服務(wù)器校驗(yàn)優(yōu)先考慮Etag
4.6.5 思維導(dǎo)圖 4.7 參考瀏覽器緩存機(jī)制介紹與緩存策略剖析
一文讀懂前端緩存
深入理解瀏覽器的緩存機(jī)制
Cookie 的本職工作并非本地存儲(chǔ),而是“維持狀態(tài)”。
Cookie 不夠大
同一個(gè)域名下的所有請(qǐng)求,都會(huì)攜帶 Cookie
5.2 Local Storage,Session Storage 5.2.1 概述存儲(chǔ)容量大: Web Storage 根據(jù)瀏覽器的不同,存儲(chǔ)容量可以達(dá)到 5-10M 之間
僅位于瀏覽器端,不與服務(wù)端發(fā)生通信。
5.2.2 Local Storage 與 Session Storage 的區(qū)別生命周期:Local Storage 是持久化的本地存儲(chǔ),存儲(chǔ)在其中的數(shù)據(jù)是永遠(yuǎn)不會(huì)過期的,使其消失的唯一辦法是手動(dòng)刪除;而 Session Storage 是臨時(shí)性的本地存儲(chǔ),它是會(huì)話級(jí)別的存儲(chǔ),當(dāng)會(huì)話結(jié)束(頁(yè)面被關(guān)閉)時(shí),存儲(chǔ)內(nèi)容也隨之被釋放。
作用域:Local Storage、Session Storage 和 Cookie 都遵循同源策略。但 Session Storage 特別的一點(diǎn)在于,即便是相同域名下的兩個(gè)頁(yè)面,只要它們不在同一個(gè)瀏覽器窗口中打開,那么它們的 Session Storage 內(nèi)容便無法共享。
5.2.3 應(yīng)用場(chǎng)景Local Storage
理論上 Cookie 無法勝任的、可以用簡(jiǎn)單的鍵值對(duì)來存取的數(shù)據(jù)存儲(chǔ)任務(wù),都可以交給 Local Storage 來做。
存儲(chǔ)一些內(nèi)容穩(wěn)定的資源。比如圖片內(nèi)容豐富的電商網(wǎng)站會(huì)用它來存儲(chǔ) Base64 格式的圖片字符串
存儲(chǔ)一些不經(jīng)常更新的 CSS、JS 等靜態(tài)資源
Session Storage
微博的 Session Storage 就主要是存儲(chǔ)你本次會(huì)話的瀏覽足跡
5.3 IndexedDBIndexedDB 是沒有存儲(chǔ)上限的(一般來說不會(huì)小于 250M)
IndexedDB 可以看做是 LocalStorage 的一個(gè)升級(jí),當(dāng)數(shù)據(jù)的復(fù)雜度和規(guī)模上升到了 LocalStorage 無法解決的程度,我們毫無疑問可以請(qǐng)出 IndexedDB 來幫忙。
6. CDN 6.1 什么是CDNCDN (Content Delivery Network,即內(nèi)容分發(fā)網(wǎng)絡(luò))指的是一組分布在各個(gè)地區(qū)的服務(wù)器。這些服務(wù)器存儲(chǔ)著數(shù)據(jù)的副本,因此服務(wù)器可以根據(jù)哪些服務(wù)器與用戶距離最近,來滿足數(shù)據(jù)的請(qǐng)求。 CDN 提供快速服務(wù),較少受高流量影響。
6.2 為什么要用 CDN緩存、本地存儲(chǔ)帶來的性能提升,是不是只能在“獲取到資源并把它們存起來”這件事情發(fā)生之后?也就是說,首次請(qǐng)求資源的時(shí)候,這些招數(shù)都是救不了我們的。要提升首次請(qǐng)求的響應(yīng)能力,我們還需要借助 CDN 的能力
6.3 CDN 如何工作假設(shè)我的根服務(wù)器在杭州,同時(shí)在圖示的五個(gè)城市里都有自己可用的機(jī)房
此時(shí)有一位北京的用戶向我請(qǐng)求資源。在網(wǎng)絡(luò)帶寬小、用戶訪問量大的情況下,杭州的這一臺(tái)服務(wù)器或許不那么給力,不能給用戶非??斓捻憫?yīng)速度。于是我靈機(jī)一動(dòng),把這批資源 copy 了一批放在北京的機(jī)房里。當(dāng)用戶請(qǐng)求資源時(shí),就近請(qǐng)求北京的服務(wù)器,北京這臺(tái)服務(wù)器低頭一看,這個(gè)資源我存了,離得這么近,響應(yīng)速度肯定噌噌的!那如果北京這臺(tái)服務(wù)器沒有 copy 這批資源呢?它會(huì)再向杭州的根服務(wù)器去要這個(gè)資源。在這個(gè)過程中,北京這臺(tái)服務(wù)器就扮演著 CDN 的角色。
6.4 CDN的核心功能CDN 的核心點(diǎn)有兩個(gè),一個(gè)是緩存,一個(gè)是回源。
緩存
“緩存”就是說我們把資源 copy 一份到 CDN 服務(wù)器上這個(gè)過程
回源
就是說 CDN 發(fā)現(xiàn)自己沒有這個(gè)資源(一般是緩存的數(shù)據(jù)過期了),轉(zhuǎn)頭向根服務(wù)器(或者它的上層服務(wù)器)去要這個(gè)資源的過程。
6.5 CDN 與前端性能優(yōu)化CDN 往往被用來存放靜態(tài)資源
“根服務(wù)器”本質(zhì)上是業(yè)務(wù)服務(wù)器,它的核心任務(wù)在于生成動(dòng)態(tài)頁(yè)面或返回非純靜態(tài)頁(yè)面,這兩種過程都是需要計(jì)算的。業(yè)務(wù)服務(wù)器仿佛一個(gè)車間,車間里運(yùn)轉(zhuǎn)的機(jī)器轟鳴著為我們產(chǎn)出所需的資源;相比之下,CDN 服務(wù)器則像一個(gè)倉(cāng)庫(kù),它只充當(dāng)資源的“棲息地”和“搬運(yùn)工”。
所謂“靜態(tài)資源”,就是像 JS、CSS、圖片等不需要業(yè)務(wù)服務(wù)器進(jìn)行計(jì)算即得的資源。而“動(dòng)態(tài)資源”,顧名思義是需要后端實(shí)時(shí)動(dòng)態(tài)生成的資源,較為常見的就是 JSP、ASP 或者依賴服務(wù)端渲染得到的 HTML 頁(yè)面。
什么是“非純靜態(tài)資源”呢?它是指需要服務(wù)器在頁(yè)面之外作額外計(jì)算的 HTML 頁(yè)面。具體來說,當(dāng)我打開某一網(wǎng)站之前,該網(wǎng)站需要通過權(quán)限認(rèn)證等一系列手段確認(rèn)我的身份、進(jìn)而決定是否要把 HTML 頁(yè)面呈現(xiàn)給我。這種情況下 HTML 確實(shí)是靜態(tài)的,但它和業(yè)務(wù)服務(wù)器的操作耦合,我們把它丟到CDN 上顯然是不合適的。
6.6 CDN 的實(shí)際應(yīng)用靜態(tài)資源本身具有訪問頻率高、承接流量大的特點(diǎn),因此靜態(tài)資源加載速度始終是前端性能的一個(gè)非常關(guān)鍵的指標(biāo)。CDN 是靜態(tài)資源提速的重要手段,在許多一線的互聯(lián)網(wǎng)公司,“靜態(tài)資源走 CDN”并不是一個(gè)建議,而是一個(gè)規(guī)定
https://www.taobao.com/
可以看到業(yè)務(wù)服務(wù)器確實(shí)是返回給了我們一個(gè)尚未被靜態(tài)資源加持過的簡(jiǎn)單 HTML 頁(yè)面
隨便點(diǎn)開一個(gè)靜態(tài)資源,可以看到它都是從 CDN 服務(wù)器上請(qǐng)求來的
6.7 cdn與cookieCookie 是緊跟域名的。同一個(gè)域名下的所有請(qǐng)求,都會(huì)攜帶 Cookie。大家試想,如果我們此刻僅僅是請(qǐng)求一張圖片或者一個(gè) CSS 文件,我們也要攜帶一個(gè) Cookie 跑來跑去(關(guān)鍵是 Cookie 里存儲(chǔ)的信息我現(xiàn)在并不需要),這是一件多么勞民傷財(cái)?shù)氖虑?。Cookie 雖然小,請(qǐng)求卻可以有很多,隨著請(qǐng)求的疊加,這樣的不必要的 Cookie 帶來的開銷將是無法想象的
同一個(gè)域名下的請(qǐng)求會(huì)不分青紅皂白地?cái)y帶 Cookie,而靜態(tài)資源往往并不需要 Cookie 攜帶什么認(rèn)證信息。把靜態(tài)資源和主頁(yè)面置于不同的域名下,完美地避免了不必要的 Cookie 的出現(xiàn)!
看起來是一個(gè)不起眼的小細(xì)節(jié),但帶來的效用卻是驚人的。以電商網(wǎng)站靜態(tài)資源的流量之龐大,如果沒把這個(gè)多余的 Cookie 拿下來,不僅用戶體驗(yàn)會(huì)大打折扣,每年因性能浪費(fèi)帶來的經(jīng)濟(jì)開銷也將是一個(gè)非??植赖臄?shù)字。
7.渲染篇(服務(wù)端渲染) 7.1 客戶端渲染客戶端渲染模式下,服務(wù)端會(huì)把渲染需要的靜態(tài)文件發(fā)送給客戶端,客戶端加載過來之后,自己在瀏覽器里跑一遍 JS,根據(jù) JS 的運(yùn)行結(jié)果,生成相應(yīng)的 DOM
我是客戶端渲染的頁(yè)面
根節(jié)點(diǎn)下到底是什么內(nèi)容呢?你不知道,我不知道,只有瀏覽器把 index.js 跑過一遍后才知道,這就是典型的客戶端渲染。
頁(yè)面上呈現(xiàn)的內(nèi)容,你在 html 源文件里里找不到——這正是它的特點(diǎn)。
7.2 服務(wù)端渲染服務(wù)端渲染的模式下,當(dāng)用戶第一次請(qǐng)求頁(yè)面時(shí),由服務(wù)器把需要的組件或頁(yè)面渲染成 HTML 字符串,然后把它返回給客戶端??蛻舳四玫绞值模强梢灾苯愉秩救缓蟪尸F(xiàn)給用戶的 HTML 內(nèi)容,不需要為了生成 DOM 內(nèi)容自己再去跑一遍 JS 代碼。
使用服務(wù)端渲染的網(wǎng)站,可以說是“所見即所得”,頁(yè)面上呈現(xiàn)的內(nèi)容,我們?cè)?html 源文件里也能找到。
7.3 服務(wù)端渲染解決了什么性能問題事實(shí)上,很多網(wǎng)站是出于效益(seo)的考慮才啟用服務(wù)端渲染,性能倒是在其次。
假設(shè) A 網(wǎng)站頁(yè)面中有一個(gè)關(guān)鍵字叫“前端性能優(yōu)化”,這個(gè)關(guān)鍵字是 JS 代碼跑過一遍后添加到 HTML 頁(yè)面中的。那么客戶端渲染模式下,我們?cè)谒阉饕嫠阉鬟@個(gè)關(guān)鍵字,是找不到 A 網(wǎng)站的——搜索引擎只會(huì)查找現(xiàn)成的內(nèi)容,不會(huì)幫你跑 JS 代碼。A 網(wǎng)站的運(yùn)營(yíng)方見此情形,感到很頭大:搜索引擎搜不出來,用戶找不到我們,誰還會(huì)用我的網(wǎng)站呢?為了把“現(xiàn)成的內(nèi)容”拿給搜索引擎看,A 網(wǎng)站不得不啟用服務(wù)端渲染。
但性能在其次,不代表性能不重要。服務(wù)端渲染解決了一個(gè)非常關(guān)鍵的性能問題——首屏加載速度過慢。在客戶端渲染模式下,我們除了加載 HTML,還要等渲染所需的這部分 JS 加載完,之后還得把這部分 JS 在瀏覽器上再跑一遍。這一切都是發(fā)生在用戶點(diǎn)擊了我們的鏈接之后的事情,在這個(gè)過程結(jié)束之前,用戶始終見不到我們網(wǎng)頁(yè)的廬山真面目,也就是說用戶一直在等!相比之下,服務(wù)端渲染模式下,服務(wù)器給到客戶端的已經(jīng)是一個(gè)直接可以拿來呈現(xiàn)給用戶的網(wǎng)頁(yè),中間環(huán)節(jié)早在服務(wù)端就幫我們做掉了,用戶豈不“美滋滋”?
7.4 服務(wù)端渲染的應(yīng)用場(chǎng)景服務(wù)端渲染本質(zhì)上是本該瀏覽器做的事情,分擔(dān)給服務(wù)器去做。這樣當(dāng)資源抵達(dá)瀏覽器時(shí),它呈現(xiàn)的速度就快了
但仔細(xì)想想,在這個(gè)網(wǎng)民遍地的時(shí)代,幾乎有多少個(gè)用戶就有多少臺(tái)瀏覽器。用戶擁有的瀏覽器總量多到數(shù)不清,那么一個(gè)公司的服務(wù)器又有多少臺(tái)呢?我們把這么多臺(tái)瀏覽器的渲染壓力集中起來,分散給相比之下數(shù)量并不多的服務(wù)器,服務(wù)器肯定是承受不住的
除非網(wǎng)頁(yè)對(duì)性能要求太高了,以至于所有的招式都用完了,性能表現(xiàn)還是不盡人意,這時(shí)候我們就可以考慮向老板多申請(qǐng)幾臺(tái)服務(wù)器,把服務(wù)端渲染搞起來了~
8.渲染篇(瀏覽器渲染) 8.1 瀏覽器內(nèi)核瀏覽器內(nèi)核可以分成兩部分:渲染引擎(Layout Engine 或者 Rendering Engine)和 JS 引擎
渲染引擎又包括了 HTML 解釋器、CSS 解釋器、布局、網(wǎng)絡(luò)、存儲(chǔ)、圖形、音視頻、圖片解碼器等等零部件。
8.2 瀏覽器渲染過程解析 8.3 基于渲染流程的 CSS 優(yōu)化建議 8.3.1 CSS 選擇符是從右到左進(jìn)行匹配的#myList li {}
瀏覽器必須遍歷頁(yè)面上每個(gè) li 元素,并且每次都要去確認(rèn)這個(gè) li 元素的父元素 id 是不是 myList
8.3.2 具體優(yōu)化避免使用通配符,只對(duì)需要用到的元素進(jìn)行選擇
關(guān)注可以通過繼承實(shí)現(xiàn)的屬性,避免重復(fù)匹配重復(fù)定義。
少用標(biāo)簽選擇器。如果可以,用類選擇器替代
不要畫蛇添足,id 和 class 選擇器不應(yīng)該被多余的標(biāo)簽選擇器拖后腿
減少嵌套。后代選擇器的開銷是最高的,因此我們應(yīng)該盡量將選擇器的深度降到最低(最高不要超過三層),盡可能使用類來關(guān)聯(lián)每一個(gè)標(biāo)簽元素
8.4 告別阻塞:CSS 與 JS 的加載順序優(yōu)化HTML、CSS 和 JS,都具有阻塞渲染的特性。
HTML 阻塞,天經(jīng)地義——沒有 HTML,何來 DOM?沒有 DOM,渲染和優(yōu)化,都是空談。
在剛剛的過程中,我們提到 DOM 和 CSSOM 合力才能構(gòu)建渲染樹。這一點(diǎn)會(huì)給性能造成嚴(yán)重影響:默認(rèn)情況下,CSS 是阻塞的資源。瀏覽器在構(gòu)建 CSSOM 的過程中,不會(huì)渲染任何已處理的內(nèi)容。即便 DOM 已經(jīng)解析完畢了,只要 CSSOM 不 OK,那么渲染這個(gè)事情就不 OK(這主要是為了避免沒有 CSS 的 HTML 頁(yè)面丑陋地“裸奔”在用戶眼前)。
只有當(dāng)我們開始解析 HTML 后、解析到 link 標(biāo)簽或者 style 標(biāo)簽時(shí),CSS 才登場(chǎng),CSSOM 的構(gòu)建才開始。很多時(shí)候,DOM 不得不等待 CSSOM。因此我們可以這樣總結(jié):
CSS 是阻塞渲染的資源。需要將它盡早、盡快地下載到客戶端,以便縮短首次渲染的時(shí)間。
盡早(將 CSS 放在 head 標(biāo)簽里)和盡快(啟用 CDN 實(shí)現(xiàn)靜態(tài)資源加載速度的優(yōu)化)
8.4.2 JS 的阻塞JS 的作用在于修改,它幫助我們修改網(wǎng)頁(yè)的方方面面:內(nèi)容、樣式以及它如何響應(yīng)用戶交互。這“方方面面”的修改,本質(zhì)上都是對(duì) DOM 和 CSSDOM 進(jìn)行修改。因此 JS 的執(zhí)行會(huì)阻止 CSSOM,在我們不作顯式聲明的情況下,它也會(huì)阻塞 DOM。
JS 引擎是獨(dú)立于渲染引擎存在的。我們的 JS 代碼在文檔的何處插入,就在何處執(zhí)行。當(dāng) HTML 解析器遇到一個(gè) script 標(biāo)簽時(shí),它會(huì)暫停渲染過程,將控制權(quán)交給 JS 引擎。JS 引擎對(duì)內(nèi)聯(lián)的 JS 代碼會(huì)直接執(zhí)行,對(duì)外部 JS 文件還要先獲取到腳本、再進(jìn)行執(zhí)行。等 JS 引擎運(yùn)行完畢,瀏覽器又會(huì)把控制權(quán)還給渲染引擎,繼續(xù) CSSOM 和 DOM 的構(gòu)建。 因此與其說是 JS 把 CSS 和 HTML 阻塞了,不如說是 JS 引擎搶走了渲染引擎的控制權(quán)。
8.4.3 JS的三種加載方式正常模式
這種情況下 JS 會(huì)阻塞瀏覽器,瀏覽器必須等待 index.js 加載和執(zhí)行完畢才能去做其它事情。
async 模式
async 模式下,JS 不會(huì)阻塞瀏覽器做任何其它的事情。它的加載是異步的,當(dāng)它加載結(jié)束,JS 腳本會(huì)立即執(zhí)行。
defer 模式
efer 模式下,JS 的加載是異步的,執(zhí)行是被推遲的。等整個(gè)文檔解析完成、DOMContentLoaded 事件即將被觸發(fā)時(shí),被標(biāo)記了 defer 的 JS 文件才會(huì)開始依次執(zhí)行。
從應(yīng)用的角度來說,一般當(dāng)我們的腳本與 DOM 元素和其它腳本之間的依賴關(guān)系不強(qiáng)時(shí),我們會(huì)選用 async;當(dāng)腳本依賴于 DOM 元素和其它腳本的執(zhí)行結(jié)果時(shí),我們會(huì)選用 defer。
9. 渲染篇(dom優(yōu)化) 10. 渲染篇(Event Loop與異步更新策略(vue)) 10.1 什么是異步更新?當(dāng)我們使用 Vue 或 React 提供的接口去更新數(shù)據(jù)時(shí),這個(gè)更新并不會(huì)立即生效,而是會(huì)被推入到一個(gè)隊(duì)列里。待到適當(dāng)?shù)臅r(shí)機(jī),隊(duì)列中的更新任務(wù)會(huì)被批量觸發(fā)。這就是異步更新。
異步更新可以幫助我們避免過度渲染,是我們上節(jié)提到的“讓 JS 為 DOM 分壓”的典范之一。
10.2 異步更新的優(yōu)越性異步更新的特性在于它只看結(jié)果,因此渲染引擎不需要為過程買單
有時(shí)我們會(huì)遇到這樣的情況
// 任務(wù)一 this.content = "第一次測(cè)試" // 任務(wù)二 this.content = "第二次測(cè)試" // 任務(wù)三 this.content = "第三次測(cè)試"
我們?cè)谌齻€(gè)更新任務(wù)中對(duì)同一個(gè)狀態(tài)修改了三次,如果我們采取傳統(tǒng)的同步更新策略,那么就要操作三次 DOM。但本質(zhì)上需要呈現(xiàn)給用戶的目標(biāo)內(nèi)容其實(shí)只是第三次的結(jié)果,也就是說只有第三次的操作是有意義的——我們白白浪費(fèi)了兩次計(jì)算。
但如果我們把這三個(gè)任務(wù)塞進(jìn)異步更新隊(duì)列里,它們會(huì)先在 JS 的層面上被批量執(zhí)行完畢。當(dāng)流程走到渲染這一步時(shí),它僅僅需要針對(duì)有意義的計(jì)算結(jié)果操作一次 DOM——這就是異步更新的妙處。
10.3 Vue狀態(tài)更新手法:nextTickVue在觀察到數(shù)據(jù)變化時(shí)并不是直接更新DOM,而是開啟一個(gè)隊(duì)列,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)改變。在緩沖時(shí)會(huì)去除重復(fù)數(shù)據(jù),從而避免不必要的計(jì)算和DOM操作。然后,在下一個(gè)事件循環(huán)tick中,Vue刷新隊(duì)列并執(zhí)行實(shí)際工作
$nextTick就是用來知道什么時(shí)候DOM更新完成的
11. 渲染篇(回流與重繪)文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/109523.html
摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...
摘要:雖然有著各種各樣的不同,但是相同的是,他們前端優(yōu)化不完全指南前端掘金篇幅可能有點(diǎn)長(zhǎng),我想先聊一聊閱讀的方式,我希望你閱讀的時(shí)候,能夠把我當(dāng)作你的競(jìng)爭(zhēng)對(duì)手,你的夢(mèng)想是超越我。 如何提升頁(yè)面渲染效率 - 前端 - 掘金Web頁(yè)面的性能 我們每天都會(huì)瀏覽很多的Web頁(yè)面,使用很多基于Web的應(yīng)用。這些站點(diǎn)看起來既不一樣,用途也都各有不同,有在線視頻,Social Media,新聞,郵件客戶端...
摘要:年求職面經(jīng)及總結(jié)我的求職之路差不多走到盡頭了感覺真是精疲力盡了把這大半年的經(jīng)歷和面試總結(jié)寫下來希望能給和我一樣在求職路上煎熬的人一點(diǎn)幫助先說背景微電子科學(xué)與工程專業(yè)學(xué)過兩門和相關(guān)的課程語言和單片機(jī)這個(gè)專業(yè)的唯一好處就是大部分人并不知道這個(gè)專 18年求職面經(jīng)及總結(jié) 我的求職之路差不多走到盡頭了,感覺真是精疲力盡了.把這大半年的經(jīng)歷和面試總結(jié)寫下來,希望能給和我一樣在求職路上煎熬的人一點(diǎn)幫...
摘要:年求職面經(jīng)及總結(jié)我的求職之路差不多走到盡頭了感覺真是精疲力盡了把這大半年的經(jīng)歷和面試總結(jié)寫下來希望能給和我一樣在求職路上煎熬的人一點(diǎn)幫助先說背景微電子科學(xué)與工程專業(yè)學(xué)過兩門和相關(guān)的課程語言和單片機(jī)這個(gè)專業(yè)的唯一好處就是大部分人并不知道這個(gè)專 18年求職面經(jīng)及總結(jié) 我的求職之路差不多走到盡頭了,感覺真是精疲力盡了.把這大半年的經(jīng)歷和面試總結(jié)寫下來,希望能給和我一樣在求職路上煎熬的人一點(diǎn)幫...
摘要:字囊括上百個(gè)前端面試題的項(xiàng)目開源了這個(gè)項(xiàng)目是什么項(xiàng)目?jī)?nèi)容這個(gè)項(xiàng)目目前在上剛剛開源主要內(nèi)容如下前端面試題主要整理了高頻且有一定難度的前端面試題對(duì)這些面試題進(jìn)行解讀前端原理詳解針對(duì)一些有一定難度面試題涉及的知識(shí)點(diǎn)進(jìn)行詳解比如涉及的編譯原理響應(yīng)式 20W字囊括上百個(gè)前端面試題的項(xiàng)目開源了 這個(gè)項(xiàng)目是什么? 項(xiàng)目?jī)?nèi)容 這個(gè)項(xiàng)目目前在GitHub上剛剛開源,主要內(nèi)容如下: 前端面試題: 主要整...
閱讀 3036·2023-04-25 20:22
閱讀 3350·2019-08-30 11:14
閱讀 2602·2019-08-29 13:03
閱讀 3191·2019-08-26 13:47
閱讀 3235·2019-08-26 10:22
閱讀 1279·2019-08-23 18:26
閱讀 628·2019-08-23 17:16
閱讀 1923·2019-08-23 17:01