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的時間,如下圖:
相比之下,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檔案大小,載入時間就會變長。
如下圖:
從上圖可以發現,轉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說明
需要注意的是,使用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)程式碼優化