爲何要有性能優化?回憶一下,當你打開一個網頁時,你能忍受的打開速度是幾秒?超過5秒你可能會當即走人。。。網站的加載速度嚴重影響了用戶體驗,也決定了這個網站的生死存亡。css
減小HTTP請求html
爲何?性能黃金法則,在HTTP請求的過程當中,只有 10%~20% 的最終用戶時間花在了下載 HTML 文檔上。其他 80%~90% 的時間花在了下載頁面中的全部組件上進行的HTTP請求上;前端
改善響應時間最簡單的途徑就是減小HTTP請求的數量; web
每下載一個圖片、js文件、css文件等等都是一次HTTP請求,因此要儘量的少下載靜態資源;數組
使用CSS雪碧圖,以前寫過一篇文章 瀏覽器
圖片地圖緩存
咱們能夠經過使用多個分開的圖片,而後每一個圖片都對應一個超連接,固然這也會產生不少HTTP請求,咱們目標是減小HTTP請求; 性能優化
圖片地圖容許你在一個圖片上關聯多個 URL。目標 URL 的選擇取決於用戶單擊了圖片上的那個位置;服務器
將多個圖片合併成一個圖片(即將多個HTTP請求減小爲一個HTTP請求),而後以位置信息定位超連接;網絡
具體用法,請移步到 https://www.w3school.com.cn/tags/att_area_coords.asp ;
儘可能合併、壓縮CSS、JS文件,或者直接寫在頁面上
使用CDN加速
通俗的說,服務器離用戶更近,HTTP 請求的響應時間將縮短;
CDN(內容發佈網絡)是一組分佈在多個不一樣地理位置的web服務器,用於更加有效地向用戶發佈內容;
借張圖說明一下:
利用緩存
CDN緩存
DNS緩存
DNS是「域名系統」的縮寫,它的工做是將域名和主機名轉化爲服務器主機的 IP 地址;
DNS查找流程:瀏覽器緩存 — 本地hosts文件 — 本地DNS解析器緩存 — 本地DNS服務器 — 本地DNS服務器設置(是否設置轉發器)— 根DNS服務器(返回一個負責該域名服務器的一個IP。本地DNS服務器會根據這個IP繼續查找服務器,若是查找到的服務器不能解析此域名,則它會找另外一個管理此域名的DNS服務器給本地DNS服務器,重複上面的動做,直到找到域名對應的主機)— 不要暈~
瀏覽器緩存之客戶端緩存
無需請求的memory cache,disk cache;
須要發請求驗證的Etag、Last-Modified304;
H5新增的 localStorage、sessionStorage;
合理利用以上緩存,能夠很大程度上提升前端性能。
HTML部分
標籤語義化,即用合理、正確的標籤來展現內容,好比 h1-h6 定義標題;
語義化的優勢:
易於用戶閱讀,樣式丟失的時候能讓頁面呈現清晰的結構;
有利於SEO,搜索引擎根據標籤來肯定上下文和各個關鍵字的權重;
方便其它設備解析,如盲人閱讀器根據語義渲染網頁;
有利於開發和維護,語義化更具可讀性,代碼更好維護,與CSS關係更和諧;
HTML很容易被網絡爬蟲識別,所以搜索引擎能夠根據網站的內容在必定程度上實時更新。在寫HTML的時候,你應該儘可能讓它簡潔而有效。舉個例子:你在寫一個網站,這個網站的其中一個模塊包括了各個高校的數據信息,而這些數據信息是實時更新的,你能夠利用爬蟲去獲取這些數據信息,若是各個高校的網站的HTML是很是符合語義化標準的,那麼你就能夠很順利的爬到這些數據信息;反之,會增長你的爬蟲代碼的難度
CSS部分
將CSS放在HTML的上面部分,這個策略不能提升網站的加載速度,但它不會讓訪問者長時間看着空白屏幕或者無格式的文本(FOUT)等待。若是網頁大部分可見元素已經加載出來了,訪問者才更有可能等待加載整個頁面,從而帶來對前端的優化效果。這就是知覺性能。
使用 link 而不是@import
加載頁面時,link標籤引入的CSS被同時加載;@import引入的CSS將在頁面加載完畢後被加載,也就是說,@import會組織瀏覽器的並行下載;
link是HTML的元素,不存在兼容性問題;@import只有IE5+才能識別;
有關link和@import的區別還有不少,推薦一篇文章 http://www.javashuo.com/article/p-bstehaet-h.html
總之,link標籤纔是最好的選擇,它也能提升網站的前端性能。
合併CSS代碼,好比用 margin 來代替 margin-top、margin-bottom、margin-left、margin-right;
減小重排,重排會致使瀏覽器從新計算整個文檔,從新構建渲染樹,這一過程會下降瀏覽器的渲染速度。咱們應該避免發生重排,下面是觸發重排的例子
改變 font-size 和 font-family;
改變元素的內外邊距;
經過JS改變CSS類;
經過JS獲取DOM元素的位置相關屬性(如width、height、left等);
CSS僞類激活;
滾動滾動條或者改變窗口大小;
減小重繪,當元素的外觀(如color、background、visibility等屬性)發生改變時,會觸發重繪。在網站的使用過程當中,重繪是沒法避免的。不過,瀏覽器對此作了優化,它會將屢次的重排、重繪操做合併爲一次執行。不過咱們仍須要避免沒必要要的重繪,如頁面滾動時觸發的hover事件,能夠在滾動的時候禁用 hover 事件,這樣頁面在滾動時會更加流暢;
減小使用昂貴的屬性,在瀏覽器繪製屏幕時,全部須要瀏覽器進行操做或計算的屬性相對而言都須要花費更大的代價。如 box-shadow、border-radius、filter、opacity、:nth-child等;
合併、壓縮CSS文件
JS部分
注意做用域,避免全局查找,訪問全局變量比訪問局部變量慢,是由於須要遍歷做用域鏈,查找做用域鏈須要額外的時間。因此在一個函數中,將訪問屢次的全局對象或者域外變量存儲爲局部變量來使用。如某個方法需引用全局變量的值,則在該方法所在的對象的做用域中定義一個局部變量等於全局變量的值。避免沒必要要的屬性查找,將屬性設置爲全局變量。
優化循環,當 if-else 較多時,建議使用 switch 語句。當分支較多時,用 switch 的效率是很高的,由於 switch 是隨機訪問的,就是肯定了值以後直接跳轉到那個特定的分支,而 if-else 是遍歷全部可能值,直到找到合適的分支;
當循環的數量很少時,展開循環;
最小化語句數,聲明多個變量時,可使用一個 var 關鍵字來聲明,變量之間用逗號表示;
使用數組或對象字面量來新建數組或對象,如 var arr = [1,2,3] ;var obj = {a:1,b:2};
JS的執行儘可能脫離DOM樹,限制DOM操做的次數優化DOM交互,在《JavaScript高級程序設計》一書有這樣一段話:在更新少許節點的時候能夠直接向 document.body 節點中添加,可是要向 document 中添加大量數據時,若是直接添加這些新節點,這個過程很是緩慢,由於每添加一個節點都會調用父節點的 appendChild() 方法,爲了解決這個問題,能夠建立一個文檔碎片,把全部新節點附加其上,而後把文檔碎片一次性添加到 document 中。
假如想建立十個段落,常規方式以下:
for(let i = 0;i < 10;i++){ let p = document.createElement("p"); let txt = document.createTextNode("段落"+i); p.appendChild(txt); document.body.appendChild(p); }
上段代碼調用了10次 document.body.appendChild(),每次都要產生一次頁面渲染。這時候能夠用文檔碎片createDocumentFragment(),
let fra = document.createDocumentFragment(); for(let i = 0;i < 10;i++){ let p = document.createElement("p"); let txt = document.createTextNode("段落"+i); p.appendChild(txt); fra.appendChild(p); } document.body.appendChild(fra);
上段代碼中,每一個新的 <p> 元素都被添加到文檔碎片中,而後這個碎片被做爲參數傳遞給 appendChild()。fra.appendChild() 實際上並非把文檔碎片加到body中,僅僅是追加碎片中的子節點。document.body.appendChild() 一次代替了10次,也就是說,只產生了一次頁面渲染,能夠看到明顯的性能提高。
使用事件代理,頁面上的事件處理程序的數量和頁面響應用戶交互的速度之間有個負相關。因此爲了減小事件處理程序,儘可能使用事件委託技術。
提升代碼的可閱讀性,好比正確標記變量,封裝某個重複的行爲,合理的註釋等。
使用cssText、className一次性改變屬性;
JS定義行爲,html定義內容,CSS定義外觀;
持續完善中,如有錯誤,歡迎指出!
參考連接
http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html
https://blog.csdn.net/qq_21891743/article/details/79642605
https://blog.csdn.net/bluedandelion/article/details/80895021