Web 性能優化的幾個策略

原文鏈接: 何曉東 博客

個人理解優化最開始需要做的是:將現有資源有效利用到極致,然後在做更多提升。開發人員多瞭解一些優化技術,不僅可以怒斥前端寫的代碼辣雞,甚至可以和架構師談笑風生。😀

在進行 web 性能優化之前,我們先重溫一下,訪問一個頁面地址到瀏覽器渲染完頁面,都有哪些過程:

資源請求/獲取流程圖:

web 資源請求/獲取流程圖

資源響應/頁面渲染流程圖:

web 資源請求/獲取流程圖

這兩張圖無需額外解釋了,所以 web 性能優化主要是針對這裏的過程進行優化,上車:

DNS 優化

在與服務主機建立連接之前,需要先解析域名;那麼,解析越快就越好。

  • 限制不同域名的數量。數量多了自然會消耗更多的解析時間,https 時代這個成本更高。
  • 保證低限度的解析延遲。瞭解你的 DNS 服務基礎設施的結構,然後從你的最終用戶分佈的所有地域定期監控解析時間。
  • 在主體頁面 HTML 或響應中利用 DNS 預取指令。例如:<link rel="dns-prefetch" href="//oss.aliyun.com>

優化TCP連接

開啓新連接是一個耗時的過程,https 有加簽名過程,更是耗時。

  • 利用 preconnect 指令,連接在使用之前就已經建立好了,這樣處理流程的關鍵路徑上就不必考慮連接時間了。 <link rel="preconnect" href="//oss.aliyun.com" crossorigin>
  • 藉助 CDN,在距離請求用戶很近的邊緣端點上,請求就可以獲得響應,

所以可以終止連接,大幅減少建立新連接的通信延遲。靜態資源上 cdn 現在成爲常態 + 廉價的優化手段了。

避免重定向

重定向通常觸發與額外域名建立連接。手機網絡環境下,重定向會增加很大延遲,畢竟iPhone 高通基帶用戶越來越多了,照顧信號差的用戶。所以可以:

  • 利用 CDN 代替客戶端在雲端實現重定向。
  • nginx 層面用 rewrite 命令搞定。

利用緩存

本地緩存:沒有什麼比直接從本地緩存獲取資源來得更快,因爲它根本就不需要建立網絡連接。最快的請求是根本不發起請求。另外,從本地獲取資源時,ISP 或 CDN 提供商不會收取流量費。設置生存時間(TTL)告訴瀏覽器應該緩存某個資源多久。找到給定資源的最佳 TTL 值並沒有完美的科學方法。設置客戶端緩存 TTL,可以通過 HTTP 首部指定 cache control 以及鍵 max-age(以秒爲單位),或者 expires 首部。

網絡緩存:對於可以共享,能夠接收一定舊數據的資料,可以在網絡邊緣緩存。主要是不需要實時性很高的資源文件可以網絡緩存。

條件緩存:如果緩存 TTL 過期,客戶端會向服務器發起請求。在多數情況下,收到的響應其實和緩存的版本是一樣的,重新下載已經在緩存裏的內容也是一種浪費。當資源不經常變化時,使用條件請求可以顯著節省帶寬和性能;可以通過以下手段使用條件緩存:

  • 在請求中包含 HTTP 首部 Last-Modified-Since。僅當最新內容在首部中指定的日期之後被更新過,服務器才返回完整內容;否則只返回 304 響應碼,並在響應首部中附帶上新的時間戳 Date 字段。
  • 在請求體中包含實體校驗碼,或者叫 ETag;它唯一標識所請求的資源。ETag 由服務器提供,內嵌於資源的響應首部中。服務器會比較當前 ETag 與請求首部中收到的 ETag,如果一致,就只返回 304 響應碼;否則返回完整內容。依然是靜態資源文件需要緩存。(可以參考 Nginx 內容緩存機制

壓縮和代碼極簡化

所有的文本內容(HTML、JS、CSS、SVG、XML、JSON、字體等),可以從壓縮和極簡
化中受益。這兩種方法組合起來,可以顯著減少資源大小。更少字節數對應着更少的請求-響應,也就意味着更短的請求時間。它通過可無損還原的算法減少資源大小。在發送資源之前,如果服務器進行壓縮處理,可以節省 90% 的大小。

極簡化是指從文本資源中剝離所有非核心內容的過程。極簡化是放棄代碼可讀性與可維護性來減少字節數,個人不推薦使用。

避免阻塞CSS/JS

儘管瀏覽器的預處理器很智能,會盡早請求整個頁面所需要的 CSS,但是把 CSS 資源請求放在頁面靠前的部分仍然是種最佳實踐,具體位置是在頁面代碼的 head 標籤裏,而且要在任何 JS 或圖片被請求和處理之前。

瀏覽器默認的阻塞行爲導致了不必要的延遲,甚至會造成單點故障。爲了減輕 JS 阻塞帶來的潛在影響,推薦使用以下策略:

  • 定期校驗這些資源的使用情況。隨着時間的變遷,Web 頁面可能會持續下載一些不再

需要的 JS;這時候,最快速有效的解決辦法就是去掉它。

  • 如果 JS 執行順序無關緊要,並且必須在 onload 事件觸發之前運行,那麼可以設置 async 屬性,例如:<script async src="/js/myfile.js">
  • 如果 JS 執行順序很重要,並且你也能承受腳本在 DOM 加載完之後運行,那麼請使用 defer 屬性,例如:<script defer src="/js/myjs.js">
  • 對不會影響到頁面初次展示的 JS 腳本,必須在 onload 事件觸發之後請求它。
  • 如果你不想延遲主頁面的 onload 事件,可以考慮通過 iframe 獲取 JS,因爲它的處理獨立於主頁面。但是,通過 iframe 下載的 JS 訪問不了主頁面上的元素。

優化圖片

圖片在現在很重要,而且高質量的圖片體積很大,移動設備訪問的時候,會有明顯的加載慢問題,同時移動端用戶耐心相對較低,所以對圖片的優化刻不容緩:

  • 去掉圖片原始的信息,尤其是照片類,會包含位置,拍照設備等信息,去掉原始信息能減少很多體積。
  • 提前裁剪圖片,然後在頁面的 js 判斷需要加載哪種尺寸的圖片,這種操作能直接選擇小尺寸圖片,對於頁面的微信分享展示也是不錯的提升。
  • 考慮第三方的圖片壓縮算法,例如 Google 的 webp 格式圖片,壓縮比例高,不會影響圖片質量。提前處理,然後加載壓縮後的圖片

參考書籍爲 《HTTP2基礎教程》,O’Reilly Media 出版社,自己調整了一些內容,希望不會收到律師函。

順道推薦點 質量不錯的付費課程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章