偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

前端性能優(yōu)化不完全手冊 【已更新至React】

開發(fā) 前端
性能優(yōu)化是一門大學問,本文僅對個人一些積累知識的闡述,歡迎下面補充。

 [[262302]]

性能優(yōu)化是一門大學問,本文僅對個人一些積累知識的闡述,歡迎下面補充。

拋出一個問題,從輸入url地址欄到所有內(nèi)容顯示到界面上做了哪些事?

  •  1.瀏覽器向 DNS 服務器請求解析該 URL 中的域名所對應的 IP 地址;
  •  2.建立TCP連接(三次握手);
  •  3.瀏覽器發(fā)出讀取文件(URL 中域名后面部分對應的文件)的HTTP 請求,該請求報文作為 TCP 三次握手的第三個報文的數(shù)據(jù)發(fā)送給服務器;
  •  4.服務器對瀏覽器請求作出響應,并把對應的 html 文本發(fā)送給瀏覽器;
  •  5.瀏覽器將該 html 文本并顯示內(nèi)容;
  •  6.釋放 TCP連接(四次揮手);

上面這個問題是一個面試官非常喜歡問的問題,我們下面把這6個步驟分解,逐步細談優(yōu)化。

一、DNS 解析

  •  DNS`解析:將域名解析為ip地址 ,由上往下匹配,只要便停止
    •   走緩存
    •   瀏覽器DNS緩存
    •   本機DNS緩存
    •   路由器DNS緩存
    •   網(wǎng)絡運營商服務器DNS緩存 (80%的DNS解析在這完成的)
    •   遞歸查詢

優(yōu)化策略:盡量允許使用瀏覽器的緩存,能給我們節(jié)省大量時間。

二、TCP的三次握手

  •  SYN (同步序列編號)ACK(確認字符)
    •   第一次握手:Client將標志位SYN置為1,隨機產(chǎn)生一個值seq=J,并將該數(shù)據(jù)包發(fā)送給Server,Client進入SYN_SENT狀態(tài),等 待Server確認。
    •   第二次握手:Server收到數(shù)據(jù)包后由標志位SYN=1知道Client請求建立連接,Server將標志位SYN和ACK都置為1,ack=J+1,隨機產(chǎn)生一個值seq=K,并將該數(shù)據(jù)包發(fā)送給Client以確認連接請求,Server進入SYN_RCVD狀態(tài)。
    •   第三次握手:Client收到確認后,檢查ack是否為J+1,ACK是否為1,如果正確則將標志位ACK置為1,ack=K+1,并將該數(shù)據(jù)包發(fā)送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態(tài),完成三次握手,隨后Client與Server之間可以開始傳輸數(shù)據(jù)了。

三、瀏覽器發(fā)送請求

優(yōu)化策略:

  •  1.HTTP協(xié)議通信最耗費時間的是建立TCP連接的過程,那我們就可以使用HTTP Keep-Alive,在HTTP 早期,每個HTTP 請求都要求打開一個TCP socket連接,并且使用一次之后就斷開這個TCP連接。 使用keep-alive可以改善這種狀態(tài),即在一次TCP連接中可以持續(xù)發(fā)送多份數(shù)據(jù)而不會斷開連接。通過使用keep-alive機制,可以減少TCP連接建立次數(shù),也意味著可以減少TIME_WAIT狀態(tài)連接,以此提高性能和提高http服務器的吞吐率(更少的tcp連接意味著更少的系統(tǒng)內(nèi)核調(diào)用
  •  2.但是,keep-alive并不是免費的午餐,長時間的TCP連接容易導致系統(tǒng)資源無效占用。配置不當?shù)膋eep-alive,有時比重復利用連接帶來的損失還更大。所以,正確地設置keep-alive timeout時間非常重要。(這個keep-alive_timout時間值意味著:一個http產(chǎn)生的tcp連接在傳送完最后一個響應后,還需要hold住keepalive_timeout秒后,才開始關閉這個連接),如果想更詳細了解可以看這篇文章keep-alve性能優(yōu)化的測試結果
  •  3.使用webScoket通信協(xié)議,僅一次TCP握手就一直保持連接,而且他對二進制數(shù)據(jù)的傳輸有更好的支持,可以應用于即時通信,海量高并發(fā)場景。webSocket的原理以及詳解
  •  4.減少HTTP請求次數(shù),每次HTTP請求都會有請求頭,返回響應都會有響應頭,多次請求不僅浪費時間而且會讓網(wǎng)絡傳輸很多無效的資源,使用前端模塊化技術 AMD CMD commonJS ES6等模塊化方案將多個文件壓縮打包成一個,當然也不能都放在一個文件中,因為這樣傳輸起來可能會很慢,權衡取一個中間值
  •  5.配置使用懶加載,對于一些用戶不立刻使用到的文件到特定的事件觸發(fā)再請求,也許用戶只是想看到你首頁上半屏的內(nèi)容,但是你卻請求了整個頁面的所有圖片,如果用戶量很大,那么這是一種極大的浪費
  •  6.服務器資源的部署盡量使用同源策略

四、服務器返回響應,瀏覽器接受到響應數(shù)據(jù)

一直沒想到這里使用什么優(yōu)化手段,今晚想到了,使用Nginx反向代理服務器,主要是對服務器端的優(yōu)化。

  •  Nginx是一款輕量級的Web 服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器,并在一個BSD-like 協(xié)議下發(fā)行。其特點是占有內(nèi)存少,并發(fā)能力強,事實上nginx的并發(fā)能力確實在同類型的網(wǎng)頁服務器中表現(xiàn)較好,中國大陸使用nginx網(wǎng)站用戶有:百度、京東、新浪、網(wǎng)易、騰訊、淘寶等。
  •  Nginx 是一個安裝非常的簡單、配置文件非常簡潔(還能夠支持perl語法)、Bug非常少的服務。Nginx 啟動特別容易,并且?guī)缀蹩梢宰龅?*24不間斷運行,即使運行數(shù)個月也不需要重新啟動。你還能夠不間斷服務的情況下進行軟件版本的升級。
  •  它可以:解決跨域,請求過濾,配置gzip,負載均衡,靜態(tài)資源服務器 等...
  •  把服務窗口想像成我們的后端服務器,而后面終端的人則是無數(shù)個客戶端正在發(fā)起請求。負載均衡就是用來幫助我們將眾多的客戶端請求合理的分配到各個服務器,以達到服務端資源的充分利用和更少的請求時間。
  •  Nginx如何實現(xiàn)負載均衡
    •   nginx如何實現(xiàn)負載均衡   
  1. Upstream指定后端服務器地址列表  
  2.    upstream balanceServer {  
  3.        server 10.1.22.33:12345;  
  4.        server 10.1.22.34:12345;  
  5.        server 10.1.22.35:12345;  
  6.    }  
  7.    復制代碼在server中攔截響應請求,并將請求轉發(fā)到Upstream中配置的服務器列表。  
  8.        server {  
  9.            server_name  fe.server.com;  
  10.            listen 80;  
  11.            location /api {  
  12.                proxy_pass http://balanceServer;  
  13.            }  
  14.        } 
  •  上面的配置只是指定了nginx需要轉發(fā)的服務端列表,并沒有指定分配策略。
  •  默認情況下采用的策略,將所有客戶端請求輪詢分配給服務端。這種策略是可以正常工作的,但是如果其中某一臺服務器壓力太大,出現(xiàn)延遲,會影響所有分配在這臺服務器下的用戶。
  •  最小連接數(shù)策略

將請求優(yōu)先分配給壓力較小的服務器,它可以平衡每個隊列的長度,并避免向壓力大的服務器添加更多的請求。   

  1. upstream balanceServer {  
  2.        least_conn; //配置壓力較小的服務器  
  3.        server 10.1.22.33:12345;  
  4.        server 10.1.22.34:12345;  
  5.        server 10.1.22.35:12345;  
  6.    } 
  •  依賴于NGINX Plus,優(yōu)先分配給響應時間最短的服務器。 
  1. upstream balanceServer {  
  2.     fair; //配置響應時間最短的服務器  
  3.     server 10.1.22.33:12345;  
  4.     server 10.1.22.34:12345;  
  5.     server 10.1.22.35:12345;  
  •  客戶端ip綁定 
  1. 來自同一個ip的請求永遠只分配一臺服務器,有效解決了動態(tài)網(wǎng)頁存在的session共享問題。  
  2. upstream balanceServer {  
  3.     ip_hash; //配置1個IP永遠只分配一臺服務器  
  4.     server 10.1.22.33:12345;  
  5.     server 10.1.22.34:12345;  
  6.     server 10.1.22.35:12345;  
  •  配置靜態(tài)資源服務器 
  1. location ~* \.(png|gif|jpg|jpeg)$ {  
  2.     root    /root/static/;    
  3.     autoindex on;  
  4.     access_log  off;  
  5.     expires     10h;# 設置過期時間為10小時    
  6.   
  7. 復制代碼匹配以png|gif|jpg|jpeg為結尾的請求,  
  8. 并將請求轉發(fā)到本地路徑,root中指定的路徑即nginx  
  9. 本地路徑。同時也可以進行一些緩存的設置
  •  Nginx解決跨域 
  1. nginx解決跨域的原理  
  2. 例如:  
  3. 前端server的域名為:fe.server.com  
  4. 后端服務的域名為:dev.server.com  
  5. 現(xiàn)在我在fe.server.com對dev.server.com發(fā)起請求一定會出現(xiàn)跨域。  
  6. 現(xiàn)在我們只需要啟動一個nginx服務器,將server_name設置為fe.server.com,  
  7. 然后設置相應的location以攔截前端需要跨域的請求,最后將請求代理回dev.server.com。  
  8. 如下面的配置:  
  9. server {  
  10.         listen       80;  
  11.         server_name  fe.server.com;  
  12.         location / {  
  13.                 proxy_pass dev.server.com;  
  14.         }  
  15.  
  16. 復制代碼這樣可以完美繞過瀏覽器的同源策略:fe.server.com訪問nginx的fe.server.com  
  17. 屬于同源訪問,而nginx對服務端轉發(fā)的請求不會觸發(fā)瀏覽器的同源策略。 
  •     最重要的一點來了,現(xiàn)在的網(wǎng)站大都使用了這種配置:
    •       配置GZIP  
      •   GZIP是規(guī)定的三種標準HTTP壓縮格式之一。目前絕大多數(shù)的網(wǎng)站都在使用GZIP傳輸 HTML、CSS、JavaScript 等資源文件。
      •   對于文本文件,GZip 的效果非常明顯,開啟后傳輸所需流量大約會降至 1/4 ~ 1/3。
      •   啟用 GZip 所需的HTTP 最低版本默認值為HTTP/1.1
      •   啟用gzip同時需要客戶端和服務端的支持,如果客戶端支持gzip的解析,那么只要服務端能夠返回gzip的文件就可以啟用gzip了,我們可以通過nginx的配置來讓服務端支持gzip。下面的respone中content-encoding:gzip,指服務端開啟了gzip的壓縮方式。
    •         具體可以看這篇文字文章 Nginx配置GZIP

對于文本文件,GZip 的效果非常明顯,開啟后傳輸所需流量大約會降至 1/4 ~ 1/3。 

Nginx功能非常強大,配置也非常方便,有興趣的可以多看看這篇文章 Nginx解析 

五、瀏覽器解析數(shù)據(jù),繪制渲染頁面的過程

  •  先預解析(將需要發(fā)送請求的標簽的請求發(fā)出去)
  •  從上到下解析html文件
  •  遇到HTML標簽,調(diào)用html解析器將其解析DOM樹
  •  遇到css標記,調(diào)用css解析器將其解析CSSOM樹
  •  link 阻塞 - 為了解決閃屏,所有解決閃屏的樣式
  •  style 非阻塞,與閃屏的樣式不相關的
  •  將DOM樹和CSSOM樹結合在一起,形成render樹
  •  layout布局 render渲染
  •  遇到script標簽,阻塞,調(diào)用js解析器解析js代碼,可能會修改DOM樹,也可能會修改CSSOM樹
  •  將DOM樹和CSSOM樹結合在一起,形成render樹
  •  layout布局 render渲染(重排重繪)
  •  script標簽的屬性
    •   async 異步 誰先回來誰就先解析,不阻塞
    •   defer 異步 按照先后順序(defer)解析,不阻塞
    •   script標簽放在body下,放置多次重排重繪,能夠操作dom

性能優(yōu)化策略:

  •  需要阻塞的樣式使用link引入,不需要的使用style標簽(具體是否需要阻塞看業(yè)務場景)
  •  圖片比較多的時候,一定要使用懶加載,圖片是最需要優(yōu)化的,webpack4中也要配置圖片壓縮,能極大壓縮圖片大小,對于新版本瀏覽器可以使用webp格式圖片webP詳解,圖片優(yōu)化對性能提升大。
  •  webpack4配置 代碼分割,提取公共代碼成單獨模塊。方便緩存   
  1. /*  
  2.     runtimeChunk 設置為 true, webpack 就會把 chunk 文件名全部存到一個單獨的 chunk 中,  
  3.     這樣更新一個文件只會影響到它所在的 chunk 和 runtimeChunk,避免了引用這個 chunk 的文件也發(fā)生改變。  
  4.     */  
  5.     runtimeChunk: true,   
  6.     splitChunks: {  
  7.       chunks: 'all'  // 默認 entry 的 chunk 不會被拆分, 配置成 all, 就可以了  
  8.     }  
  9.   }  
  10.     //因為是單入口文件配置,所以沒有考慮多入口的情況,多入口是應該分別進行處理。 
  •  對于需要事件驅動的webpack4配置懶加載的,可以看這篇webpack4優(yōu)化教程,寫得非常全面
  •  一些原生javaScript的DOM操作等優(yōu)化會在下面總結

六、TCP的四次揮手,斷開連接

終結篇:性能只是 load 時間或者 DOMContentLoaded 時間的問題嗎?

  •  RAIL
    •   Responce 響應,研究表明,100ms內(nèi)對用戶的輸入操作進行響應,通常會被人類認為是立即響應。時間再長,操作與反應之間的連接就會中斷,人們就會覺得它的操作有延遲。例如:當用戶點擊一個按鈕,如果100ms內(nèi)給出響應,那么用戶就會覺得響應很及時,不會察覺到絲毫延遲感。
    •   Animaton 現(xiàn)如今大多數(shù)設備的屏幕刷新頻率是60Hz,也就是每秒鐘屏幕刷新60次;因此網(wǎng)頁動畫的運行速度只要達到60FPS,我們就會覺得動畫很流暢。
    •   Idle RAIL規(guī)定,空閑周期內(nèi)運行的任務不得超過50ms,當然不止RAIL規(guī)定,W3C性能工作組的Longtasks標準也規(guī)定了超過50毫秒的任務屬于長任務,那么50ms這個數(shù)字是怎么得來的呢?瀏覽器是單線程的,這意味著同一時間主線程只能處理一個任務,如果一個任務執(zhí)行時間過長,瀏覽器則無法執(zhí)行其他任務,用戶會感覺到瀏覽器被卡死了,因為他的輸入得不到任何響應。為了達到100ms內(nèi)給出響應,將空閑周期執(zhí)行的任務限制為50ms意味著,即使用戶的輸入行為發(fā)生在空閑任務剛開始執(zhí)行,瀏覽器仍有剩余的50ms時間用來響應用戶輸入,而不會產(chǎn)生用戶可察覺的延遲。
    •   Load如果不能在1秒鐘內(nèi)加載網(wǎng)頁并讓用戶看到內(nèi)容,用戶的注意力就會分散。用戶會覺得他要做的事情被打斷,如果10秒鐘還打不開網(wǎng)頁,用戶會感到失望,會放棄他們想做的事,以后他們或許都不會再回來。

如何使網(wǎng)頁更絲滑?

  •   使用requestAnimationFrame
    •    即便你能保證每一幀的總耗時都小于16ms,也無法保證一定不會出現(xiàn)丟幀的情況,這取決于觸發(fā)JS執(zhí)行的方式。假設使用 setTimeout 或 setInterval 來觸發(fā)JS執(zhí)行并修改樣式從而導致視覺變化;那么會有這樣一種情況,因為setTimeout 或 setInterval沒有辦法保證回調(diào)函數(shù)什么時候執(zhí)行,它可能在每一幀的中間執(zhí)行,也可能在每一幀的最后執(zhí)行。所以會導致即便我們能保障每一幀的總耗時小于16ms,但是執(zhí)行的時機如果在每一幀的中間或最后,最后的結果依然是沒有辦法每隔16ms讓屏幕產(chǎn)生一次變化,也就是說,即便我們能保證每一幀總體時間小于16ms,但如果使用定時器觸發(fā)動畫,那么由于定時器的觸發(fā)時機不確定,所以還是會導致動畫丟幀?,F(xiàn)在整個Web只有一個API可以解決這個問題,那就是requestAnimationFrame,它可以保證回調(diào)函數(shù)穩(wěn)定的在每一幀最開始觸發(fā)。
  •   避免FSL
    •    先執(zhí)行JS,然后在JS中修改了樣式從而導致樣式計算,然后樣式的改動觸發(fā)了布局、繪制、合成。但JavaScript可以強制瀏覽器將布局提前執(zhí)行,這就叫 強制同步布局FSL。 
  1. //讀取offsetWidth的值會導致重繪  
  2.             const newWidth = container.offsetWidth;    
  3.               //設置width的值會導致重排,但是for循環(huán)內(nèi)部  
  4.              代碼執(zhí)行速度極快,當上面的查詢操作導致的重繪  
  5.              還沒有完成,下面的代碼又會導致重排,而且這個重  
  6.              排會強制結束上面的重繪,直接重排,這樣對性能影響  
  7.              非常大。所以我們一般會在循環(huán)外部定義一個變量,這里  
  8.              面使用變量代替container.offsetWidth;  
  9.             boxes[i].style.width = newWidth + 'px';  
  10.            }      
  •   使用transform屬性去操作動畫,這個屬性是由合成器單獨處理的,所以使用這個屬性可以避免布局與繪制。
  •   使用translateZ(0)開啟圖層,減少重繪重排。特別在移動端,盡量使用transform代替absolute。創(chuàng)建圖層好的方式是使用will-change,但某些不支持這個屬性的瀏覽器可以使用3D 變形(transform: translateZ(0))來強制創(chuàng)建一個新層。
  •   有興趣的可以看看這篇文字 前端頁面優(yōu)化
  •   樣式的切換提前定義好class,通過class的切換批量修改樣式,避免多次重繪重排
  •   可以先切換display:none再修改樣式
  •   多次的append 操作可以先插入到一個新生成的元素中,再一次性插入到頁面中。
  •   代碼復用,函數(shù)柯里化,封裝高階函數(shù),將多次復用代碼封裝成普通函數(shù)(俗稱方法),React中封裝成高階組件,ES6中可以使用繼承,TypeScript中接口繼承,類繼承,接口合并,類合并。
  •   強力推薦閱讀:阮一峰ES6教程
  •   以及什么是TypeScript以及入門

以上都是根據(jù)本人的知識點總結得出,后期還會有更多性能優(yōu)化方案等出來,路過點個贊收藏收藏~,歡迎提出問題補充~

下面加入React的性能優(yōu)化方案:

  •  在生命周期函數(shù)shouldComponentUpdate中對this.state和prev state進行淺比較,使用for-in循環(huán)遍歷兩者,

只要得到他們每一項值,只要有一個不一樣就返回true,更新組件。

  •  定義組件時不適用React.component , 使用PureComponent代替,這樣React機制會自動在shouldComponentUpdate中進行淺比較,決定是否更新。
  •  上面兩條優(yōu)化方案只進行淺比較,只對比直接屬性的值,當然你還可以在上面加入this.props和prevprops的遍歷比較,因為shouldComponentUpdate的生命周期函數(shù)自帶這兩個參數(shù)。如果props 和 state 的值比較復雜,那么可以使用下面這種方式去進行深比較。
  •     解決:
    •   保證每次都是新的值
    •   使用 immutable-js 庫,這個庫保證生成的值都是獨立的       
  1. var map1 = Immutable.Map({ a: 1, b: 2, c: 3 });  
  2.         var map2 = map1.set('b', 50);  
  3.         map1.get('b'); // 2  
  4.         map2.get('b'); // 50 
  •  總結:使用以上方式,可以減少不必要的重復渲染。
  •  React的JSX語法要求必須包裹一層根標簽,為了減少不必要的DOM層級,我們使用Fragment標簽代替,這樣渲染時候不會渲染多余的DOM節(jié)點,讓DIFF算法更快遍歷。
  •  使用Redux管理全局多個組件復用的狀態(tài)。
  •  React構建的是SPA應用,對SEO不夠友好,可以選擇部分SSR技術進行SEO優(yōu)化。
  •  對Ant-design這類的UI組件庫,進行按需加載配置,從import Button from 'antd' 的引入方式,變成import {Button} from antd的方式引入。(類似Babel7中的runtime和polifill的區(qū)別).

 

 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2015-09-01 10:42:15

編程規(guī)范完全指南

2019-07-04 08:47:57

JavaScript瀏覽器技術

2015-10-10 10:02:44

程序員面試指南

2021-06-01 06:03:28

Css前端CSS 特效

2014-09-19 10:03:18

Chrome

2024-01-02 16:43:58

2011-06-29 10:03:33

Qt Configure

2017-04-13 08:46:41

oracle數(shù)據(jù)挖掘

2024-01-12 10:16:53

2021-05-06 07:26:55

CSS 文字動畫技巧

2021-02-09 00:46:45

區(qū)塊鏈加密貨幣工具

2016-09-27 15:08:22

JavascriptLanguage TaWeb

2021-08-18 10:28:09

MySQL SQL 語句數(shù)據(jù)庫

2017-04-19 20:10:20

SQLJOIN

2019-08-18 22:45:22

編程Rust語言

2025-04-30 06:55:30

AI人工智能直播

2019-08-19 16:01:59

Rust編程語言JavaScript

2024-04-22 08:49:29

CIO人工智能云計算

2011-05-12 10:49:39

2011-08-30 09:35:10

OracleRMAN不完全恢復基于時間恢復
點贊
收藏

51CTO技術棧公眾號