Effective前端--加快頁面開啟速度

alex99發表於2018-09-28

1.避免head標籤JS阻塞

  所有放在head標籤裡的JS和CSS都會阻塞頁面渲染。如果這些CSS和JS需要記在時間比較久,中間頁面會存在一個空白期,嚴重影響到使用者體驗。

  例如以下程式碼:在head標籤內載入jquery的js檔案,

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta http-equiv="X-UA-Compatible" content="ie=edge">

<title>demo</title>

<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
複製程式碼

  jquery.js指令碼檔案載入了1.2s的時間,如下圖:   

Effective前端--加快頁面開啟速度

  相比之下,html載入的時間只有2ms,所以這個JS檔案至少頁面停留了1.2s的空白狀態。

  解決方法:1.使用script標籤將js指令碼檔案放在body後面

       2.使用HTML5的新增屬性defer,給script標籤價上defer屬性,一旦加上該屬性,script將會非同步載入,但不是馬上執行,而是等readystatechange變為Interactive後按照順序執行。

2.減少head標籤裡的CSS資源

  (1)不要放太多base64放在CSS裡面

   放太多base64在CSS裡面,會導致CSS急速膨脹,把一張3k的圖片轉換為base64,體積將變為4k;如果你的css檔案中放了10張3k的base64圖片,CSS檔案的體積將變為40k,可想而知,圖片放的越多,越會增大css檔案大小,載入時間就會變長。

   如下圖:

Effective前端--加快頁面開啟速度

  從上圖可以發現,轉base64後,圖片體積增大了接近1/3,我們的目的是為了減小CSS、JS載入時間的,而非增加時間(不考慮不同網速環境)。

  (2)把CSS寫成內聯的

  為什麼這樣說呢,我們寫CSS的時候,總是被告誡少些內聯樣式,易於維護。但是如果你的CSS只有10K或者30-40k,把它寫成內聯的未嘗不可,吧專案的CSS檔案gzip之後如果很小,完全可以把所有的CSS都寫成style標籤放到HTML裡面。

  如果你把CSS放到CDN上,瀏覽器為了得到這個CSS檔案,需要進行域名解析,然後建立http/https連結,其次才是下載此檔案。而用來做域名解析和建立連線的時間早已經把CSS下載下來了。

  為了避免時間開銷,更好的使用者瀏覽速度,可以把CSS直接嵌到HTML裡面。

  如果你的CSS檔案不是太大,加上gzip壓縮,放到HTML中會是一個不錯的選擇。

 3.優化圖片

  (1)使用響應式圖片

    響應式圖片的優點就是能夠根據瀏覽器的螢幕大小、裝置畫素比dpr、橫豎屏自動載入合適的圖片

    <img srcset='phtoto_w350.jpg 1x,photo_w640.jpg 2x' src='photo_w350.jpg' alt=''>
複製程式碼

    上述程式碼實現如果螢幕的dpr=1的話載入1倍圖,而dpr=2則載入2倍圖。並且,如果瀏覽器不支援srcset屬性,會預設載入src裡面的圖片。

    網上說,在MAC上的CHorme會載入srcset裡面的2x圖片的同時,還會去載入src裡面的那張,載入兩張圖片。哈哈,由於本人比較窮,無mac,不能驗證了。有的小夥伴可以驗證下

  另外HTML5新增的picture標籤,對實現響應式圖片做了很多擴充套件。不想敲了,借用MDN說明

Effective前端--加快頁面開啟速度

    需要注意的是,使用picture標籤時必須使用img標籤,否則無法顯示。對picture的操作最後都是在img標籤上體現,例如onload事件是在img標籤出發的,picture和source是不會被瀏覽器layout的,他們的寬和高都是0.

    在栗子2中,可以使用type=‘image/webp’,從而使用webp格式的圖片,webp圖片在保持同等清晰度的情況下,體積可以減少一半,但是相容性不太好,目前只有chorme支援。但是如果檢查到不支援此格式,會預設選擇img標籤內的圖片。

  (2)延遲載入圖片

    這個是大眾常談的,基本上都很熟悉,簡單說一下

    頁面內圖片過多的情況下,如果一口氣載入完,會導致頁面的loaded時間較長,並且由於下載並行的資源有限制的,圖片太多會導致放在body後的JS解析會比較慢,頁面會較長時間處在不可互動的狀態。

    懶載入圖片這時就排上用場了,初始載入的時候只載入首屏圖片,不在視口內的圖片,只有在使用者下滑至相應位置才去載入。

    具體做法:渲染圖片的時候 把圖片地址放到標籤的一個data屬性上,別放到src上。如下:

    <picture>
    
    <source data-srcset="mdn-logo.svg" type="image/svg+xml">
    
    <img src="about:blank" data-src='mdn-logo.png' alt="MDN">
    
    </picture>
複製程式碼

    src裡不能寫一個不存在的地址,否則瀏覽器控制檯會報錯。載入失敗,如果寫成空或者不寫,那麼src會預設當前頁面。寫成about:blank,不會報錯,瀏覽器相容性也很好。

    監聽scroll事件,回撥函式如下:

showImage(leftSpace = 500){

var scrollTop = $window.scrollTop();

var $containers = this.$imgContainers,

      scrollPosition = $window.scrollTop() + $window.height();

for(var i =0;i<$containers.length;i++){

    var $container = $containers.eq(i);

    if($container.ofset().top() - scrollPosition < leftSpace){

          this.ensureImgSrc($container)       

    }         

    }         

}
複製程式碼

    使用ensureImgSrc函式把圖片放出來

ensureImgSrc($container){

var $source = $cotainer.find("source");

if($source.length && !$source.attr('srcset')){

      $source.attr('srcset',$source.data('srcset'));     

  } 

  var $img= $cotainer.find("img:not(.loading)");

  if($img.length && !$img.attr('src').indexOf('//')<0》){

      $img.attr('src',$source.data('src'));

      this.shownCount++;

  } 

    }       
複製程式碼

  另外當圖片被載入完畢後,要清楚監聽事件,否則會造成記憶體洩漏。

int(){  
    //初始化  
    var leftSpace = 0;  
    this.showImage(leftSpace);  
    //監聽事件  
    $window.on("scroll",this,this.throttleShow);     
    }
ensureImgSrc($container){

    //如果全部顯示,off掉scroll    
    if(this.showCount>=this.allCount){        
       $window.off("scroll",this.throttleShow)   
    }
    
}
複製程式碼

  (3) 壓縮和快取

   gzip壓縮和伺服器設定快取。需要後臺Nginx配置。接觸不深,不做見解

4.其他優化方式

(1)升級到HTTP/2

    http2的有點在於對於一個域只建立一次TCP連線,使用多路複用,傳輸多個資源,這樣就不用使用注入雪碧圖、合併js/css檔案等技術減少請求數,它可以同時載入多個資源,不用進行資源排隊。

(2)DNS預讀取

<link rel="dns-prefetch"  href="https://www.google.com/">
複製程式碼

  提前解析DNS,多個並行,不會堵塞頁面渲染,可以減少資源載入時間

 (3)HTML優化

    remove掉多餘註釋,刪除行前縮排,都會減少HTML的體積

 (4)程式碼優化

相關文章