互聯網有一項著名的8秒原則。用戶在訪問Web網頁時,若是時間超過8秒就會感到不耐煩,若是加載須要太長時間,他們就會放棄訪問。大部分用戶但願網頁能在2秒以內就完成加載。javascript
事實上,加載時間每多1秒,你就會流失7%的用戶。8秒並非準確的8秒鐘,只是向網站開發者代表了加載時間的重要性。那咱們如何優化頁面性能,提升頁面加載速度呢?這是本文主要要探討的問題,然而性能優化是個綜合性問題,沒有標準答案,想要面面俱到羅列出來,並不是易事。本文只關注一些核心要點,如下是我總結性能優化常見的方法:css
1、資源壓縮與合併 主要包括這些方面:html壓縮、css 壓縮、js的壓縮和混亂和文件合併。 資源壓縮能夠從文件中去掉多餘的字符,好比回車、空格。你在編輯器中寫代碼的時候,會使用縮進和註釋,這些方法無疑會讓你的代碼簡潔並且易讀,但它們也會在文檔中添加多餘的字節。html
1.html壓縮前端
html代碼壓縮就是壓縮這些在文本文件中有意義,可是在HTML中不顯示的字符,包括空格,製表符,換行符等,還有一些其餘意義的字符,如HTML註釋也能夠被壓縮。java
如何進行html壓縮:node
使用在線網站進行壓縮(開發過程當中通常不用) nodejs 提供了html-minifier工具 後端模板引擎渲染壓縮web
2.css代碼壓縮:算法
css代碼壓縮簡單來講就是無效代碼刪除和css語義合併chrome
如何進行css壓縮:編程
使用在線網站進行壓縮(開發過程當中通常不用) 使用html-minifier工具 使用clean-css對css壓縮
3.js的壓縮和混亂
js的壓縮和混亂主要包括如下這幾部分:
1.無效字符的刪除 2.剔除註釋 3.代碼語義的縮減和優化 4.代碼保護(代碼邏輯變得混亂,下降代碼的可讀性,這點很重要)
如何進行js的壓縮和混亂
1.使用在線網站進行壓縮(開發過程當中通常不用) 2.使用html-minifier工具 3.使用uglifyjs2對js進行壓縮
其實css壓縮與js的壓縮和混亂比html壓縮收益要大得多,同時css代碼和js代碼比html代碼多得多,經過css壓縮和js壓縮帶來流量的減小,會很是明顯。因此對大公司來講,html壓縮無關緊要,但css壓縮與js的壓縮和混亂必需要有!
4.文件合併
從上圖能夠看出不合並請求有如下缺點:
文件與文件之間有插入的上行請求,增長了N-1個網絡延遲 受丟包問題影響更嚴重 keep-alive方式可能會出現情況,通過代理服務器時可能會被斷開,也就是說不能一直保持keep-alive的狀態 壓縮合並css和js能夠減小網站http請求的次數,但合併文件可能會帶來問題:首屏渲染和緩存失效問題。那該如何處理這問題呢?----公共庫合併和不一樣頁面的合併。
如何進行文件合併
1.使用在線網站進行文件合併 2.使用nodejs實現文件合併(gulp、fis3)
2、非核心代碼異步加載異步加載的方式
一、異步加載的方式 異步加載的三種方式——async和defer、動態腳本建立
① async方式
async屬性是HTML5新增屬性,須要Chrome、FireFox、IE9+瀏覽器支持 async屬性規定一旦腳本可用,則會異步執行 async屬性僅適用於外部腳本 若是是多個腳本,該方法不能保證腳本按順序執行
<script type="text/javascript" src="xxx.js" async="async"></script>
複製代碼
② defer方式
兼容全部瀏覽器 defer屬性規定是否對腳本執行進行延遲,直到頁面加載爲止 若是是多個腳本,該方法能夠確保全部設置了defer屬性的腳本按順序執行 若是腳本不會改變文檔的內容,可將defer屬性加入到script標籤中,以便加快處理文檔的速度
③動態建立script標籤 在還沒定義defer和async前,異步加載的方式是動態建立script,經過window.onload方法確保頁面加載完畢再將script標籤插入到DOM中,具體代碼以下:
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function(){
addScriptTag("js/index.js");
}
複製代碼
二、異步加載的區別 1)defer是在HTML解析完以後纔會執行,若是是多個,按照加載的順序依次執行
2)async是在加載完以後當即執行,若是是多個,執行順序和加載順序無關
其中藍色線表明網絡讀取,紅色線表明執行時間,這倆都是針對腳本的;綠色線表明 HTML 解析。
3、利用瀏覽器緩存
對於web應用來講,緩存是提高頁面性能同時減小服務器壓力的利器。
瀏覽器緩存類型
1.強緩存:
不會向服務器發送請求,直接從緩存中讀取資源,在chrome控制檯的network選項中能夠看到該請求返回200的狀態碼,而且size顯示from disk cache或from memory cache;
相關的header: Expires :response header裏的過時時間,瀏覽器再次加載資源時,若是在這個過時時間內,則命中強緩存。它的值爲一個絕對時間的GMT格式的時間字符串, 好比Expires:Thu,21 Jan 2018 23:39:02 GMT
Cache-Control :這是一個相對時間,在配置緩存的時候,以秒爲單位,用數值表示。當值設爲max-age=300時,則表明在這個請求正確返回時間(瀏覽器也會記錄下來)的5分鐘內再次加載資源,就會命中強緩存。好比Cache-Control:max-age=300,
簡單歸納:其實這二者差異不大,區別就在於 Expires 是http1.0的產物,Cache-Control是http1.1的產物,二者同時存在的話,Cache-Control優先級高於Expires;在某些不支持HTTP1.1的環境下,Expires就會發揮用處。因此Expires實際上是過期的產物,現階段它的存在只是一種兼容性的寫法。強緩存判斷是否緩存的依據來自因而否超出某個時間或者某個時間段,而不關心服務器端文件是否已經更新,這可能會致使加載文件不是服務器端最新的內容,那咱們如何獲知服務器端內容較客戶端是否已經發生了更新呢?此時咱們須要協商緩存策略。
2.協商緩存: 向服務器發送請求,服務器會根據這個請求的request header的一些參數來判斷是否命中協商緩存,若是命中,則返回304狀態碼並帶上新的response header通知瀏覽器從緩存中讀取資源;另外協商緩存須要與cache-control共同使用。
相關的header: ①Last-Modified和If-Modified-Since:當第一次請求資源時,服務器將資源傳遞給客戶端時,會將資源最後更改的時間以「Last-Modified: GMT」的形式加在實體首部上一塊兒返回給客戶端。
Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
複製代碼
客戶端會爲資源標記上該信息,下次再次請求時,會把該信息附帶在請求報文中一併帶給服務器去作檢查,若傳遞的時間值與服務器上該資源最終修改時間是一致的,則說明該資源沒有被修改過,直接返回304狀態碼,內容爲空,這樣就節省了傳輸數據量 。若是兩個時間不一致,則服務器會發回該資源並返回200狀態碼,和第一次請求時相似。這樣保證不向客戶端重複發出資源,也保證當服務器有變化時,客戶端可以獲得最新的資源。一個304響應比一個靜態資源一般小得多,這樣就節省了網絡帶寬。
但last-modified 存在一些缺點:
Ⅰ.某些服務端不能獲取精確的修改時間
Ⅱ.文件修改時間改了,但文件內容卻沒有變
既然根據文件修改時間來決定是否緩存尚有不足,可否能夠直接根據文件內容是否修改來決定緩存策略?----ETag和If-None-Match
②ETag和If-None-Match:Etag是上一次加載資源時,服務器返回的response header,是對該資源的一種惟一標識,只要資源有變化,Etag就會從新生成。瀏覽器在下一次加載資源向服務器發送請求時,會將上一次返回的Etag值放到request header裏的If-None-Match裏,服務器只須要比較客戶端傳來的If-None-Match跟本身服務器上該資源的ETag是否一致,就能很好地判斷資源相對客戶端而言是否被修改過了。若是服務器發現ETag匹配不上,那麼直接以常規GET 200回包形式將新的資源(固然也包括了新的ETag)發給客戶端;若是ETag是一致的,則直接返回304知會客戶端直接使用本地緩存便可。
二者之間對比:
首先在精確度上,Etag要優於Last-Modified。Last-Modified的時間單位是秒,若是某個文件在1秒內改變了屢次,那麼他們的Last-Modified其實並無體現出來修改,可是Etag每次都會改變確保了精度;若是是負載均衡的服務器,各個服務器生成的Last-Modified也有可能不一致。 第二在性能上,Etag要遜於Last-Modified,畢竟Last-Modified只須要記錄時間,而Etag須要服務器經過算法來計算出一個hash值。 第三在優先級上,服務器校驗優先考慮Etag
緩存的機制
強制緩存優先於協商緩存進行,若強制緩存(Expires和Cache-Control)生效則直接使用緩存,若不生效則進行協商緩存(Last-Modified / If-Modified-Since和Etag / If-None-Match),協商緩存由服務器決定是否使用緩存,若協商緩存失效,那麼表明該請求的緩存失效,從新獲取請求結果,再存入瀏覽器緩存中;生效則返回304,繼續使用緩存。主要過程以下:
[圖片上傳失敗...(image-15d2b1-1540127191385)]
用戶行爲對瀏覽器緩存的影響 1.地址欄訪問,連接跳轉是正經常使用戶行爲,將會觸發瀏覽器緩存機制;
2.F5刷新,瀏覽器會設置max-age=0,跳過強緩存判斷,會進行協商緩存判斷;
3.ctrl+F5刷新,跳過強緩存和協商緩存,直接從服務器拉取資源。
4、使用CDN
大型Web應用對速度的追求並無止步於僅僅利用瀏覽器緩存,由於瀏覽器緩存始終只是爲了提高二次訪問的速度,對於首次訪問的加速,咱們須要從網絡層面進行優化,最多見的手段就是CDN(Content Delivery Network,內容分發網絡)加速。經過將靜態資源(例如javascript,css,圖片等等)緩存到離用戶很近的相同網絡運營商的CDN節點上,不但能提高用戶的訪問速度,還能節省服務器的帶寬消耗,下降負載。
CDN是怎麼作到加速的呢?
其實這是CDN服務商在全國各個省份部署計算節點,CDN加速將網站的內容緩存在網絡邊緣,不一樣地區的用戶就會訪問到離本身最近的相同網絡線路上的CDN節點,當請求達到CDN節點後,節點會判斷本身的內容緩存是否有效,若是有效,則當即響應緩存內容給用戶,從而加快響應速度。若是CDN節點的緩存失效,它會根據服務配置去咱們的內容源服務器獲取最新的資源響應給用戶,並將內容緩存下來以便響應給後續訪問的用戶。所以,一個地區內只要有一個用戶先加載資源,在CDN中創建了緩存,該地區的其餘後續用戶都能所以而受益。
5、預解析DNS
資源預加載是另外一個性能優化技術,咱們可使用該技術來預先告知瀏覽器某些資源可能在未來會被使用到。 經過 DNS 預解析來告訴瀏覽器將來咱們可能從某個特定的 URL 獲取資源,當瀏覽器真正使用到該域中的某個資源時就能夠儘快地完成 DNS 解析。例如,咱們未來可從 example.com 獲取圖片或音頻資源,那麼能夠在文檔頂部的 <head>
標籤中加入如下內容:
<link rel="dns-prefetch" href="//example.com">
複製代碼
當咱們從該 URL 請求一個資源時,就再也不須要等待 DNS 的解析過程。該技術對使用第三方資源特別有用。經過簡單的一行代碼就能夠告知那些兼容的瀏覽器進行 DNS 預解析,這意味着當瀏覽器真正請求該域中的某個資源時,DNS 的解析就已經完成了,從而節省了寶貴的時間。
另外須要注意的是,瀏覽器會對a標籤的href自動啓用DNS Prefetching,因此a標籤裏包含的域名不須要在head中手動設置link。可是在HTTPS下不起做用,須要meta來強制開啓功能。這個限制的緣由是防止竊聽者根據DNS Prefetching推斷顯示在HTTPS頁面中超連接的主機名。下面這句話做用是強制打開a標籤域名解析
<meta http-equiv="x-dns-prefetch-control" content="on">
複製代碼
若是以爲文章對你有些許幫助,點贊和關注,感激涕零!
這裏推薦一下個人前端學習交流羣:784783012,裏面都是學習前端的,若是你想製做酷炫的網頁,想學習編程。本身整理了一份2018最全面前端學習資料,從最基礎的HTML+CSS+JS【炫酷特效,遊戲,插件封裝,設計模式】到移動端HTML5的項目實戰的學習資料都有整理,送給每一位前端小夥伴,有想學習web前端的,或是轉行,或是大學生,還有工做中想提高本身能力的,正在學習的小夥伴歡迎加入學習。