本文提供一個優化網頁性能的大概思路,具體操做網上資料不少。css
性能優化第一步,即是管理好頁面的緩存,避免重複下載資源。不然,即增長服務器壓力,又折磨用戶的錢包。html
訪問頁面,請求各類資源,瀏覽器檢查本地是否有緩存。css3
若是有,檢查資源是否過時。沒過時,直接使用緩存。過時了,便向服務器發出請求。瀏覽器
發出的請求中會帶上etag和last-modified首部字段。緩存
服務器會經過Etag和last-modified來判斷瀏覽器緩存的資源是否已經不可用。性能優化
若是資源仍然有效,便返回304告知瀏覽器使用緩存。不然返回更新後的資源。服務器
按照這一套邏輯,即可規劃好網站的緩存。async
一般沒法作到這一點,由於瀏覽器發現資源沒過時,根本不會發出請求。 可是能夠經過修改資源的網址來實現。因此須要給資源文件名加上版本號或者隨機標記。例如 style.1234.css。 也就是說,不要讓瀏覽器緩存html文件,不然,過時以前,瀏覽器都不會請求服務器。函數
最好的優化,即是根本不下載資源。因此要儘可能減小比不要的資源。工具
評估全部依賴是否必要,權衡利弊。
依賴的下載路徑是否可靠,不可用時候是否會阻礙整個頁面。
產品設計時候就須要拋棄浪費帶寬的設計。
去掉沒必要要的圖片
多使用css3來代替圖片
使用壓縮率更高的圖片。特別是gif動圖,一些視頻格式(H.264或WebM)的體積比gif小不少。
用藝術字字體,不要用圖片
仔細權衡圖片和文字的關係。要表達一個意思,可能一圖勝千言。多了一張圖片,反而節省了大量文字。
使用progressive jpeg。相比隨着數據下載從上到下顯示的baseline jpeg,progressive jpeg是由模糊到清晰,用戶體驗好,也不會致使reflow。
圖片分辨率要儘量小,避免圖片分辨率大於顯示分辨率。
爲使用更新瀏覽器的用戶提供更現代的圖片格式。
多種分辨率的位圖供不一樣頁面大小使用。
要給標籤指明寬高,不然會致使reflow。
使用HTTP/2。好比,精靈圖是由不少小圖片組成的一張大圖片,能夠減小http請求。可是卻難以緩存,修改一個小圖片,致使全部小圖片緩存失效。HTTP/2,一個連接內能夠發起多個請求,便無需使用精靈圖。
@font-face 中unicode-range能夠制定字符範圍,用來避免下載不須要的語言的字符。
確保字體都被壓縮過。
用@font-face的display屬性和FontFace對象管理好字體加載時的邏輯。
瀏覽器渲染一張網頁經過如下步驟。
處理 HTML 標記並構建 DOM 樹。
處理 CSS 標記並構建 CSSOM 樹。
將 DOM 與 CSSOM 合併成一個渲染樹。
根據渲染樹來佈局,以計算每一個節點的幾何信息。
將各個節點繪製到屏幕上。
優化關鍵渲染路徑,即是指優化這個渲染過程,讓網頁儘快呈現出來。
CSS文件會阻塞渲染。瀏覽器構建好DOM樹後,必須等待CSSOM樹構建完成。
在文檔頂部防止外聯CSS的標籤,讓瀏覽器儘快請求CSS文件。
避免在css文件中使用@import,由於只有包含import的文件被下載編譯後,瀏覽器纔會發現並下載import的css。
能夠考慮使用內聯CSS,無需額外請求,不會阻塞渲染。
在CSSOM構建完成前,js不會開始執行。
js也會阻止DOM樹構建。除非在 <script>
標籤上標記async。
用Chrome開發者工具的audits檢查網頁。
重繪過程
選擇器越複雜,瀏覽器計算得越久。最糟狀況下,瀏覽器須要遍歷整個DOM-tree,計算量等於元素總個數乘以選擇器個數。
儘可能不要使選擇器太複雜,事先給須要被操做的元素加上類名。
Chrome, Opera, Safari, Internet Explorer中叫layout. 火狐稱之爲Reflow。
reflow, repaint次數越少越好,牽連的元素越少越好。
reflow老是牽涉整個文檔流。
修改元素css後馬上讀取css計算值,將致使瀏覽器同步reflow,阻塞js線程。
瀏覽器渲染網頁時,會將網頁分層(layer),最後將不一樣層合併,而後完成渲染。 同一層中,哪怕只有一個小小的元素髮生變化,整個層都會被repaint。 這一點能夠在開發者工具的Paint Profiler界面中觀察到,layer界面中能夠觀察網頁有多少個layer。
paint是耗費性能的。
修改transform和opacity會致使repaint
建立新layer來減小repaint區域。
will-change屬性能夠爲元素建立新layer(works in Chrome, Opera and Firefox).或 transform: translateZ(0);(works in all browsers).
過多layer也消耗內存和性能,用Performance判斷新layer是否帶來優化,不然不要建立新layer。
高dpi屏幕下,fixed元素自動擁有本身的layer。低dpi須要自行建立。
repaint某個layer時,若是layer與其餘元素重疊,將致使layer和重疊的元素都被repaint。
最好的動畫是跳過layout和paint直接composite。
用transform, opacity來製做動畫,可實現無layout和repaint. (Devtool Performance的main中無動畫相關事件。)
debounce:不要高頻率調用函數,事件連續觸發時,只調用一次函數。
交互事件的監聽函數的執行時間不能太長,不然會阻塞頁面滾動。
不要再交互事件的監聽函數中修改樣式,會致使強制同步reflow,阻塞js執行。
debounce,活用requestAnimationFrame方法。
監聽函數可能會調用perventDefault, 致使compositor線程必須等待監聽函數執行完成。 不過新擴展的addEventListener方法第三個參數能夠解決此問題。
動畫不能低於60幀。ui反饋不能低於100ms。
ui反饋沒必要追求最快,可故意拖延到100ms。並利用這個時間作其餘事。
儘可能增長線程空閒時間,以快速反饋。
ui反饋優先級最高,交互期間儘可能停下其餘任務。