幾個月前面試的時候問我效能優化我可能會開始背誦雅虎軍規,加點
webp
,程式碼層面稍稍講點,現在系統的梳理下效能優化的方方面面
本文涉及方面有:
-
程式碼優化
-
網路請求過程角度入手
-
DNS
解析 -
TCP
建立連結 -
網路往返時延(
RTT
) -
資料傳輸
-
-
網路問題角度入手
-
請求數量
-
流量
-
-
效能優化測試工具
程式碼優化
css
程式碼優化
避免類正則的屬性選擇器
CSS3
新增了複雜的屬性選擇器,可以通過類正規表示式的方式對元素的屬性值進行匹配。當然這些型別的選擇器定是會影響效能的,正規表示式匹配會比基於類別的匹配會慢很多。大部分情況下我們應儘量避免使用 *=, |=, ^=, $=, 和 ~=語法的屬性選擇器。
合寫CSS
除了壓縮的方式,我們還可以通過少寫CSS屬性來達到減少CSS位元組的目的
利用繼承CSS
css
的繼承機制也可以幫我們再一定程度上縮減位元組數,我們知道CSS有很多屬性是可以繼承的即在父容器設定了默寫屬性,子容器會預設也使用這些屬性,因此如果我們希望全文字型尺寸是14px,大可不必為每個容器設定,只需要在body上設定就可以了。應用這個技巧,把CSS屬性在可能的情況下提到父容器是可以幫我們節省CSS位元組的,順便說一下哪些屬性可以繼承
-
所有元素可繼承:
visibility
和cursor
-
內聯元素和塊元素可繼承:
letter-spacing、word-spacing、white-space、line-height、color、font、 font-family、font-size、font-style、font-variant、font-weight、text- decoration、text-transform、direction
-
塊狀元素可繼承:
text-indent
和text-align
-
列表元素可繼承:
list-style、list-style-type、list-style-position、list-style-image
-
表格元素可繼承:
border-collapse
-
不可繼承的:
display、margin、border、padding、background、height、min-height、max- height、width、min-width、max-width、overflow、position、left、right、top、 bottom、z-index、float、clear、table-layout、vertical-align、page-break-after、 page-bread-before
不用CSS
表示式
不亂用CSS reset
或屬性設定
避免適用萬用字元或隱式萬用字元
javascript
程式碼優化
儘量使用原生方法
javaScript是解釋性語言,相比編譯性語言執行速度要慢。瀏覽器已經實現的方法,就不要再去實現一遍了。另外,瀏覽器已經實現的方法在演算法方面已經做了很多優化
不要型別轉換
JavaScript
是動態型別,但如果你想提高速度不要使用該功能。儘量保持變數的型別一致。這也適用於陣列,儘管主要是由瀏覽器都進行了優化,但儘量不要混用不同型別的陣列
避免使用不支援的語法
優化編譯器不支援一些特定的語句, 使用這些語法會使包含它的函式無法得到優化.
有一點請注意, 即使這些語句無法到達或者不會被執行, 它們也會使相關函式無法被優化
目前不會被優化的有:
-
generator
函式 -
包含
for...of
語句的函式 -
包含
try...catch
的函式 -
包含
try...finally
的函式 -
包含複合
let
賦值語句的函式 (原文為 compound let assignment) -
包含複合
const
賦值語句的函式 (原文為 compound const assignment) -
包含含有
__proto__
或者get/set
宣告的物件字面量的函式
可能永遠不會被優化的有:
-
包含
debugger
語句的函式 -
包含字面呼叫
eval()
的函式 -
包含
with
語句的函式
處理方法
之前提到過的一些語句在生產環境中是無法避免的, 比如 try...finally
和 try...catch
. 為了是代價最小, 它們必須被隔離到一個最小化的函式, 以保證主要的程式碼不受影響.
使用微類庫
通常開發者都會使用JavaScript
類庫,如jQuery、Mootools、YUI、Dojo
等,但是開發者往往只是使用JavaScript
類庫中的部分功能。為了更大的提升效能,應儘量避免使用這類大而全的類庫,而是按需使用微類庫來輔助開發
用做標記的變數儘可能使用布林型別
直接用true和false做標記,不要使用數字或者字串的1和0來做標記。
jquery
最佳實踐
網路請求角度入手
正常的一次網路請求會經歷4個過程,分別是:
DNS
解析 ->TCP
建立連結 -> 網路往返時延(RTT
) -> 資料傳輸,面臨的挑戰可以總結為時延較高、頻寬有限、流量有成本,具體各過程面臨的挑戰和優化措施如下。
-
DNS
解析-
主要挑戰:解析耗時長
-
優化措施
-
減少域名
-
首屏在3個域名內
-
減少
DNS
查詢,避免重定向。瀏覽器DNS
快取 、計算機DNS
快取、 伺服器DNS
快取、使用Keep-Alive
特性 來減少DNS
查詢。
-
參考資料: DNS解析
-
-
TCP
連線-
主要挑戰:除了TCP握手會多一次網路往返,另外在移動端網路建立
TCP
連結前,還需要進行信令的互動,在2G環境下影響最為明顯 -
優化措施(複用)
-
HTTP2.0
多路複用HTTP/2
可以很容易的去實現多流並行而不用依賴建立多個 TCP 連線,HTTP/2 把 HTTP 協議通訊的基本單位縮小為一個一個的幀,這些幀對應著邏輯流中的訊息。並行地在同一個 TCP 連線上雙向交換訊息。單連線多資源的方式,減少服務端的連結壓力,記憶體佔用更少,連線吞吐量更大 由於 TCP 連線的減少而使網路擁塞狀況得以改善,同時慢啟動時間的減少,使擁塞和丟包恢復速度更快
-
HTTP1.1
持久連線
-
參考資料:知乎HTTP2.0
-
-
網路往返時延(
RTT
)-
主要挑戰:耗時長
-
優化措施(複用、合併、就近接入)
-
就近接入
-
靜態資源:接入
CDN
-
動態資料
接入移動運營商和小運營商反向代理進行加速
-
-
合併請求,減少請求數量
-
首屏禁止301、302跳轉
-
合併樣式和指令碼
-
使用
css
圖片精靈 -
首屏必須小圖片使用
base64
格式內嵌入HTML
-
初始首屏之外的圖片資源按需載入,靜態資源延遲載入
-
合併外聯程式碼
-
-
快取
-
抽出公共程式碼複用快取
-
使用
LocalStorage
等快取資料 -
圖片/外鏈程式碼開啟快取
-
-
參考資料:知乎合併 HTTP 請求是否真的有意義?
-
-
資料傳輸
-
主要挑戰:頻寬有限、流量有成本
-
優化措施(複用、壓縮、分包)
-
壓縮
-
圖片優化
不需要背景透明的採用jpg代替png 使用webp 使用合適尺寸的圖片,而不是對圖片進行拉伸
-
開啟
GZIP
-
壓縮程式碼
-
靜態資源使用不帶
cookie
的域名
-
-
複用
HTTP 304
-
-
網路問題角度入手
頁面在網路上遇到的問題可以總結為一個或多個網路請求以及每個請求的流量問題,在請求數量以及每個請求的流量固定的情況下,可以通過優化請求順序以及合理劃分流量來提升使用者體驗,請求順序和流量劃分通常遇到的問題和優化措施如下。
-
請求
-
-
主要挑戰:
沒有充分利用有限的併發數量,序列載入資料
可以預先載入的操作沒有預先載入
無用請求搶佔併發數量 -
優化
-
DNS
的預解析
可以通過用meta
資訊來告知瀏覽器, 我這頁面要做DNS預解析<meta http-equiv="x-dns-prefetch-control" content="on" />
可以使用link標籤來強制對DNS做預解析:
<link rel="dns-prefetch" href="http://ke.qq.com/" />
-
HTTP
管線化
HTTP管線化可以克服同域並行請求限制帶來的阻塞,它是建立在持久連線之上,是把所有請求一併發給伺服器,但是伺服器需要按照順序一個一個響應,而不是等到一個響應回來才能發下一個請求,這樣就節省了很多請求到伺服器的時間。不過,HTTP管線化仍舊有阻塞的問題,若上一響應遲遲不回,後面的響應都會被阻塞到。 -
刪除無用請求
-
-
-
流量
-
主要挑戰:各種流量混在一起載入,流量之間沒有優先順序
-
優化措施(延遲載入)
-
延遲載入非首屏程式碼(拆分首屏css,首屏js)
-
延遲載入非首屏資料
懶載入,螢幕滾動到才載入 -
延遲載入非首屏圖片
輪播圖片等第一張圖片載入後再載入後面其他圖片
-
-
網站效能工具
YSLOW
會按照雅虎軍規分析網站
Page Speed Online
Google Page Speed 是當下很流行的線上測試網站效能工具,基於Google的一套最佳的前端效能的規則,你可以很方便得到大量的效能資訊,甚至還提供了移動裝置的最佳實踐報告。
Show Slow
它能從三個流行的測試工具YSlow,Page Speed和DynaTrace定期獲取測試資料進行總結對比,免費,但需要註冊。