web性能優化指南

前端性能優化,是每一個前端必備的技能,優化本身的代碼,使本身的網址能夠更加快速的訪問打開,減小用戶等待,今天就會從幾個方面提及前端性能優化的方案,javascript

看下面的一張圖,常常會被面試官問,從輸入URL到頁面加載完成,發生了什麼?css

 

 

1.用戶輸入www.baidu.com
2.瀏覽器經過DNS。吧url解析ip
3.和ip地址創建TCP鏈接,發送HTTP請求
4.服務器接收請求,查庫,讀文件等,拼接好 返回的HTTP響應
5.瀏覽器收到首屏html,開始渲染,
6.解析html位dom
7.解析css爲css-tree
8.dom+css生成render-tree繪圖
9.加載script的js文件
10.執行js文件
 
DNS緩存
 DNS是「域名系統」的縮寫,它的工做是將域名和主機名轉化爲服務器主機的 IP 地址;
  DNS查找流程:瀏覽器緩存 — 本地hosts文件 — 本地DNS解析器緩存 — 本地DNS服務器 — 本地DNS服務器設置(是否設置轉發器)— 根DNS服務器

 瀏覽器緩存之客戶端緩存html

    無需請求的memory cache,disk cache;前端

    須要發請求驗證的Etag、Last-Modified304;vue

    H5新增的 localStorage、sessionStorage;java

  合理利用以上緩存,能夠很大程度上提升前端性能。node

  網站存在緩存怎麼解決?
  1.文件加哈希
       1.上線以後,要求用戶強刷新,這種問題,用文件名加指紋方式解決
       2. a.hash.js  hash是整個a.js文件的md5值,文件內容不變,hash不變,緩存生效
  2.緩存文件怎麼解決
   1.加時間戳 <script src="/a.js?_t=xx">
   2.加版本號 <script src="/a.js?_v=1.6"> 好比jq,vue公用庫,內容沒有改變 從新加載
   3.加指紋 可是不產生新文件 <script src="/a.js?h=abcd12sa"> 不能清除Cdn緩存,可是生成新文件,會有問題(html,js那個先上)
   4.最終,誕生最優的產生文件<script src="/a.abcd12sa.js">先上js,在上html webpack build 打包
 
優化策略
 1.長鏈接
  2.減小文件體積    
   1.js打包壓縮 
      1.無效字符的刪除、剔除註釋、代碼語義的縮減與優化、代碼保護
      2.使用在線網站壓縮、使用 html-minifier 對html 中的 js 進行壓縮、使用uglifyjs2 對 js 進行壓縮
      2.圖片壓縮
      1.把網站上用到的一些圖片整合到一張單獨的圖片中
      3.css壓縮
     1.無效代碼刪除、css語義合併
      2.使用在線網站壓縮、使用 html-minifier 對html 中的 css 進行壓縮、使用clean-css 對 css 進行壓縮
   4.html 壓縮
     1.壓縮在文本文件中有意義可是在HTML中不顯示的字符,包括空格、製表符、換行符、註釋等
      2.使用在線網站壓縮、nodejs提供了html-minifier 工具、後端模板引擎渲染壓縮
   5.開啓 gzip
   6.文件合併

    1.若是不合並 === > 文件與文件之間有插入的上行請求,增長了N - 1 個網絡延遲;受丟包問題影響更嚴重;通過代理服務器時可能會被斷開webpack

    2.若是合併 === > 首屏渲染時間變長; 文件緩存大面積失效nginx

    3.公共庫合併、不一樣頁面的合併git

    4.使用在線網站進行文件合併、使用 nodejs 實現文件合併

 3.減小文件請求次數
      1.雪碧圖
      2.js,css打包
      3.緩存控制
      4.懶加載
 4.減小用戶和服務器的距離
  (地理位置)
       1.cdn  js能夠推到cdn緩存上
 5.本地存儲
 6.圖片大小計算
  對於一張 100  100 像素的圖片來講,圖像上有 10000 個像素點,若是每一個像素的值是 RGBA 存儲的話,那麼也就是說每一個像素有 4 個通道,每一個通道 1 個字節(8 位 = 1個字節),因此該圖片大小大概爲 39KB(10000  * 4 / 1024)。可是在實際項目中,一張圖片可能並不須要使用那麼多顏色去顯示,咱們能夠經過減小每一個像素的調色板來相應縮小圖片的大小。
 
 瀏覽器緩存機制
  經過網絡獲取內容及速度緩存慢有開銷巨大,較大相應須要在客戶端與服務器之間進行屢次往返通訊,這回延遲瀏覽器得到處理內容的時間,還會增長訪問者流量的費用,所以,緩存重複利用以前獲取的資源能力成爲性能優化的一個關鍵方面
  廣義的緩存,能夠分爲四個,你們對httpcache比較熟悉
      1.Http Cache
      2.Service Worker Cache
      3.Memory Cache
      4.Push Cache

  Http Cache
   瀏覽器大佬:須要獲取main.js,看下強緩存裏有沒有
      1.Expires和Cache-Control兩個header來控制強緩存

   2.expires: Mon, 16 Mar 2020 09:50:27 GMT

   3.last-modified: Thu, 15 Feb 2018 14:17:52 GMT

  Memory Cache

    內存緩存,短命,好比經常使用數據js裏,瀏覽器也有本身的策略,base64圖片,體積小的靜態資源

  Service Worker Cache

    是一種獨立於主幹線程以外的javascript線程,它脫離於瀏覽器窗體,算是幕後工做,能夠實現離線緩存,網絡代理等

圖片優化

  圖片一般是最佔用流量的,pc端加載平均圖片大小是600k,簡直比js打包後的文件還大,因此針對圖片的優化,不一樣場景,使用不一樣文化的類型
   1. jpg   
    1.有壓縮
       2.體積小,不支持透明
         3.用於背景圖,輪播圖

  2.png

    1.無壓縮,質量高,支持透明
       2.色彩線條更豐富,小圖,好比logo,商品icon
   3.svg
    1.文本,體積小,矢量圖
       2.渲染成本,學習成本
   4.圖片打成雪碧圖,減小http請求次數
 
gzip
  Http壓縮就是以縮小體積爲目的,對HTTP內容進行從新編碼的過程
  Gzip壓縮背後的原理,是在一個文本文件中找出一些重複出現的字符串,臨時替換他們,從而、使整個文件變小,根據這個原理,文件找那個代碼重複率越高,那麼壓縮的效率越高,使用Gzip收益就越大,反之亦然基原本說Gzip都是服務器乾的活,好比nginx
 
本地存儲
  常見本地存儲格式有 cookie  localstroage sessionStroage  indexDB
   1.cookie
      最先,體積先定。性能浪費,全部請求都帶上全部的當前域名的。

    由於 http 請求無狀態,因此須要 cookie 去維持客戶端狀態

    cookie 生成方式:http response header 中的 set-cookie; js 中能夠經過document.cookie讀寫cookie

    使用:用於瀏覽器端和服務器端的交互;客戶端自身數據的存儲

    過時時間:expire

    存儲限制:做爲瀏覽器存儲,大小4kb左右;須要設置過時時間 expire

    cookie 存儲能力被 localstorage 代替

    httponly 不容許 js 讀寫

    cookie 中在相關域名下面 --- cdn的流量損耗 。 解決:cdn 的域名和主站的域名要分開

  2.Web Storage
      1.存儲量大,不自動發個服務器,js控制
   2.localstroage
     HTML5 設計出來專門用於瀏覽器存儲的
       大小爲 5M 左右
     僅在客戶端使用,不和服務端進行通訊
     接口封裝較好
     瀏覽器本地緩存方案
   3.sessionStroage
    會話級別的瀏覽器存儲
    大小爲 5M 左右
    僅在客戶端使用,不和服務端進行通訊
    接口封裝較好
    對於標表單信息的維護
  3.indexDB
      運行在瀏覽器上的非關係型數據庫
  4.pwa
   基於緩存技術的應用模型
     可靠:在沒有網絡的環境中也能提供基本的頁面訪問
    快速:針對網頁渲染及網絡數據訪問有較好的優化
         融入:應用能夠被增長到手機桌面,而且和普通應用同樣有全屏、推送等特性

重繪與迴流

   迴流:當咱們對DOM修改引起了DOM幾何尺寸的變化(好比修改元素的寬,高度或者隱藏元素等)時,瀏覽器須要從新計算元素的幾何屬性,(其餘元素的幾何屬性和位置也會所以受到影響),而後再將計算的結果繪製出來,這個過程就是迴流(也加劇排)
 
   重繪:當咱們對DOM的修改致使了樣式的變化,卻並未影響幾何屬性,(好比修改了顏色和背景色)時,瀏覽器不須要從新計算元素的幾何屬性,直接爲該元素繪製新的樣式,(跳過了上圖所示的迴流環節)。這個過程叫作重繪
 
  由此咱們能夠看出,重繪不必定致使迴流,迴流必定致使重繪
 
  迴流是影響最大的
      1.窗體,字體大小
      2.增長樣式表
      3.內容變化
      4.class屬性
      5.offserWidth和offsetHeight
      6.fixed
節流和防抖
  節流
    預約一個函數只有在大於等於執行週期時才執行,週期內調用不執行
// 函數節流  每隔多少時間執行一次
        const throttle = (func ,wait = 100) =>{
            // 不管調用多少次,函數都是100毫秒執行一次
            let lastTime =0;
            return(...args) =>{
                let now = new Date().getTime()
                if(now - lastTime >wait) {
                    func.apply(this.args)
                    lastTime = now
                }
            }
        }

        let i =1;
        window.addEventListener('scroll',throttle(()=>{
            // 使用作圖片懶加載
            console.log(i)
            i+=1
        },350)) 

  

  防抖
    在函數須要頻繁觸發時,只有當有足夠空閒的時間時,才執行一次
/* 
            校驗用戶是否是重複,用戶輸入完,向後端發送請求
            若是用戶每次輸入,都發生請求,形成請求過多
            用戶中止輸入字符串350毫秒,在發出
        */

        const debounce = (func,wait = 350) =>{
            let timer =0;
            return (...args)=>{
                if(timer) {
                    clearInterval(timer)
                }
                timer = setTimeout(() => {
                    func.apply(this,args)
                }, wait);
            }
        }

        let i =1;
        window.addEventListener('scroll',debounce(()=>{
            // 驗證
            console.log(i)
            i+=1
        },350))

  lazy-load

  對於一些圖片多,頁面長的網頁來講,若是每次打開頁面加載所有的網頁內容,頁面加載速度勢必會受到影響,若是每次打開網頁只將網頁可視區域的內容加載給用戶 ,將大大提升網頁瀏覽速度,同時也減輕服務器負載,咱們可使用lazyload.js來實現對圖片的延遲加載,當網頁圖片進入到瀏覽器可視區域時,纔會去請求服務器加載圖片。

  

// 獲取全部的圖片
        const img = document.getElementsByTagName('img')
        // 獲取可視區域的高度
        const viewHeight = window.innerHeight || document.documentElement.clientHeight;
        // num用於計算當前顯示到那一張圖片,避免每次都是從第一張開始檢查是否漏出
        let num =0;
        function lazyload() {
            for(let i=num;i<img.length;i++) {
                // 用但是區域高度減去元素頂部距離可視區域頂部的高度
                let distance = viewHeight - img[i].getBoundingClientRect().top
                // 若是可視區域高度大於等於元素頂部距離可視區域頂部的高度,說明元素露出
                if(distance >=0) {
                    // 給元素寫入真實的src,展現圖片
                    img[i].src = img[i].getAttribute('data-src')
                    // 前i張圖片已經加載完畢,,下次從第i+1張開始檢查是否露出
                    num = i+1
                }
            }
        }
        // 監聽scroll
        window.addEventListener('scroll',lazyload,false)

 

performance.getEntriesByType('navigation')  性能檢測

  經過在瀏覽器控制檯輸入這個命令,就能夠檢測到網頁加載數據,檢測網頁加載性能

  

 

 

 

  列入:
      DNS查詢耗時 經過使用domainLookupEnd - domainLookupStart  就等於dns查詢的時間
      TCP連接耗時  經過 connectEnd - connectStart
      HTTP請求耗時 經過 responseEnd - responseStart 
      解析dom樹耗時  經過 domComplete -  domInteractive
      白屏時間 經過 responseStart  - navigationStart
      DOMready時間 經過 domContentLoadedEventEnd - navigationStart
      onload時間 經過 loadEventEnd -  navigationStart 也便是onload回調函數執行的時間
 
Lighthouse插件
Lighthouse分析web應用程序和web頁面,收集關於開發人員最佳實踐的現代性能指標和看法,讓開發人員根據生成的評估頁面,來進行網站優化和完善,提升用戶體驗。
  1.能夠在谷歌商店安裝一個Lighthouse一個插件就能夠了,下面我是檢測github網站的數據
  2.使用node全局安裝
npm install -g lighthouse

  安裝完以後運行,也是找的github網址,運行成功以後,會彈出一個生成的html頁面。

 

 生成一個html文件,找到而後直接打開就行

 

 

 

 瀏覽器渲染

  

  1.在這一步瀏覽器執行了全部的加載解析邏輯,在解析HTML的過程當中發出了頁面渲染所須要的各類外部資源請求
  2.瀏覽器將識別並加載全部的css樣式信息與dom樹合併,最終勝出頁面render樹,(:after :brfore這樣的僞元素在這個環節被構建到DOM樹中)
  3.頁面中全部元素相對位置信息,大小等信息均在這一步獲得計算
  4.在這一步瀏覽器會根據咱們的DOM代碼結果,把每個頁面圖層轉換爲像素,並對全部的媒體文件進行解碼
  5.最後一步瀏覽器會合並各個圖層,講數據有CPU輸給GPU最終繪製在屏幕上,(複雜的視圖會給這個階段GPU計算帶來一些壓力,在實際中是爲了優化動畫性能,咱們有時候會手動區分各個視圖)
 
  渲染過程說白了,首先是基於HTML構建一個DOM樹,這顆DOM樹與css解析器解析除的CSSOM相結合,就有了佈局渲染樹,最後瀏覽器以佈局渲染樹爲藍本,去計算佈局並繪製圖像,咱們頁面初次渲染就大功告成了。
   
  以後每當一個新元素加入到這個DOM樹中,瀏覽器便會經過css引擎查遍css樣式表,找到符合該元素的樣式應用到這個元素上,而後在從新去繪製他
 
服務端渲染 等等.....
以上就是所總結的常見的前端性能優化,若有不足,但願大佬多多指點指點
相關文章
相關標籤/搜索