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