前端優化之 Http 相關優化總結

Http 優化方式是前端性能優化的重要部分,也是前端必備的知識點之一。javascript

減小靜態資源文件大小

這個是最根本的途徑,假設真的有個 10 幾兆以上的靜態資源文件,不減小大小的狀況下,即便優化作到了極致,用戶體驗也好不了哪裏去。css

若是整個網頁就 2KB 大小的資源文件,不優化都很快。html

代碼層優化

  • 只打包用到的依賴包,目前 webpack tree shaking 功能已經自動處理了,還有儘可能少使用第三方依賴包(固然看狀況啦)。
  • 代碼分割(code splitting),不一樣頁面加載本身用到的代碼,不加載其餘頁面的代碼(其實也屬於懶加載)。

傳輸層優化

Http 傳承啓用壓縮傳輸方式。前端

通常咱們開啓 gzip,基本都能壓縮 6 倍左右(通常都是文件越大,字符串類似率越大,壓縮率越大)。java

首先通過服務器壓縮後,而後 Http 響應頭 Content-Encoding 設置爲相應的壓縮方式,瀏覽器會自動解壓的。webpack

Content-Encoding: gzip
複製代碼

固然還有其餘的壓縮方式,如 compress、deflate 等等,目前使用最廣的仍是 gzip。web

適當合併或者分散請求

合併請求或者分散請求須要看實際狀況的。算法

合併請求

http 1.1 (包括 http1.1)以前的版本,瀏覽器存在同域名併發限制,谷歌目前是同域名併發如今爲6 個請求,其餘的瀏覽器或多或少,但也差不了多少。segmentfault

若是是使用的是 http1.1 web 服務,那麼咱們首次加載的資源要基本保證在 4 個之內,因此靜態資源請求數過多就要看狀況進行合併請求了。瀏覽器

分散請求

Http2.0 沒有同域名併發的問題,咱們能夠適當分散請求。固然若是在 Http1.1 一個資源文件過大,而後併發並無達到限制,也能夠拆分資源文件達到分散請求的目的。

使用預加載

預加載某些狀況下能夠大大提高加載速度進而提示用戶體驗。

預加載須要瞭解 preloadprefetch 的知識。

預加載 DNS

dns 解析也是須要時間的,特別在移動端的時候更明顯,咱們能夠預解析 dns 減小不通域名 dns 解析時間。

<link rel="dns-prefetch" href="//example.com">
複製代碼

其實還有個 preconnectpreconnect 不只完成 DNS 預解析,同時還將進行 TCP 握手和創建傳輸層協議,可是瀏覽器有兼容性,目前用不上。

<link rel="preconnect" href="http://example.com">
複製代碼

預加載靜態資源

使用 preload

經過 preload 通常是預加載當前頁面要用到的圖片、字體、js 腳本、css 文件等靜態資源文件。

場景一

若是須要,你能夠徹底以腳本化的方式來執行這些預加載操做。例如,咱們在這裏建立一個HTMLLinkElement 實例,而後將他們附加到 DOM 上:

var preloadLink = document.createElement("link");
preloadLink.href = "myscript.js";
preloadLink.rel = "preload";
preloadLink.as = "script";
document.head.appendChild(preloadLink);
複製代碼

這意味着瀏覽器將預加載這個JavaScript文件,但並不實際執行它。

若是要對其加以執行,在須要的時候,你能夠執行:

var preloadedScript = document.createElement("script");
preloadedScript.src = "myscript.js";
document.body.appendChild(preloadedScript);
複製代碼

當你須要預加載一個腳本,但須要推遲到須要的時候才令其執行時,這種方式會特別有用。

場景二

字體是要使用到的時候纔會去加載字體的(若是字體是自定義的字體,會發起 Http 請求加載字體)。

因爲這個特性,咱們能夠預加載字體,待使用到字體的時候,字體已經加載完畢,無需等待加載。

以下咱們沒有 preload 的時候,代碼也是能夠運行的,可是字體加載是須要等待頁面 JS、CSS 資源加載完畢後,當前頁面使用到字體纔會去加載的:

<style> @font-face { font-family: Test-Number-Medium; src: url(./static/font/Test-Number-Medium.otf); } </style>
複製代碼

咱們加上:

<link rel="preload" href="./static/font/Test-Number-Medium.otf">
複製代碼

就能夠提交加載,節省大部分甚至所有的字體加載時間,通常都是所有的時間,由於 JS 資源文件比字體大多了(並行下載,最長的資源加載時間,決定了最大加載時間)。

使用 prefech

prefetch 通常是預加載非當前頁面的資源,prefetch 是一個低優先級的資源提示,容許瀏覽器在後臺(空閒時)獲取未來可能用獲得的資源,而且將他們存儲在瀏覽器的緩存中。當前頁面加載完畢,纔會開始下載 d帶有 prefetch 標記的資源,而後當用戶進入另一個頁面,已經 prefetched 的資源能夠馬上從緩存中加載。

不過 prefech 的應用場景比較少。

<link rel="prefetch" href="/uploads/images/pic.png">
複製代碼

採用懶加載

圖片懶加載

這種作法通常都是在用戶滾動到響應位置(固然從用戶體驗式來講,須要提早一點加載),纔會加載響應的圖片,圖片特別多的網上基本都會作這個優化(如視頻網站)。

或者幻燈片查看圖片的時候,用戶即將查查下一張圖片的時候再加載,而不是一次性加載所有的圖片。

JS 懶加載

須要用到相關 JS 時,經過動態建立 <script> 標籤進行 JS 文件懶加載,如 Webpack 的 code splitting

合理使用 defer 和 async

帶有 deferasync 屬性的 script 資源都會並行下載,並且不會影響頁面的解析,從而達到了節省腳本下載時間

兩種的不一樣的在於:

帶有 defer 屬性的資源會按照順序在頁面出現的屬性,資源加載完後,會在 DOMContentLoaded事件調用以前依次執行。

帶有 async 屬性的資源則是下載完當即執行,可能在 DOMContentLoaded 事件以前或者以後執行,多個帶有 async 屬性的資源無執行順序,誰先加載完成,誰先執行。

那麼爲何能夠節省下載時間?咱們來對比一下。

defer 資源加載相似於把 <script> 放在 </body> 前,可是 defer 資源能夠和 <head> 的資源並行下載,那麼就能夠節省部分甚至所有的下載時間(看 <head> 資源和 defer 資源大小)。因此咱們何以適當的把 defer 資源放在 <head>,某些場景是能夠提高必定的速度。

async 資源有點相似於 </body> 前的 script 資源加載完成後,動態建立 <script> 標籤加載資源,可是卻要等待頁面 JS 文件執行以後才能夠加載,而 async 資源無需等待便可提早加載,就能夠節省必定的加載時間。因此比較適合加載如谷歌分析百度統計日誌上報等類型的 js 資源,都是獨立運做也不影響頁面的輔助 js 資源。

利用緩存

緩存對於再次訪問相同資源來講,是個極大的優化,緩存是 http 優化的必經之道。對於 css 和 js 這些靜態資源文件,咱們通常都是用強緩存(例如緩存30天),強緩存無需再次向服務請求靜態資源。 可是強緩存若是使用不當,那麼會對用戶形成意想不到的 bug,如入口 html 文件就不能被強緩存了,不然版本更新後,用戶在緩存期間是沒法訪問到新版的頁面。

詳細能夠看下本人的另外一篇緩存相關的文章,瀏覽器之HTTP緩存的那些事

使用 Http2.0

Http2.0 多路複用解決了多域名併發如今問題,能夠節省資源整體的下載時間,還有請求頭壓縮和差別傳輸也會提升傳輸效率。

多路複用

HTTP1.1 持久鏈接解決了鏈接複用問題,但仍是存在着一個問題,一個 TCP 沒法併發處理請求:在一個 TCP 鏈接中,同一時間只可以發送一個請求,而且須要等響應完成纔可以發送第二個請求。

HTTP2.0 使用了多路複用的技術,作到同一個鏈接併發處理多個請求,並且併發請求的數量比 HTTP1.1 大了好幾個數量級。

固然 HTTP1.1 也能夠多創建幾個 TCP 鏈接,來支持處理更多併發的請求,可是建立TCP鏈接自己也是有開銷的。

TCP 鏈接有一個預熱和保護的過程,先檢查數據是否傳送成功,一旦成功過,則慢慢加大傳輸速度。所以對應瞬時併發的鏈接,服務器的響應就會變慢。因此最好能使用一個創建好的鏈接,而且這個鏈接能夠支持瞬時併發的請求。

多路複用能帶來哪些優化呢?

有多路複用特性,那麼瀏覽器對同一域名的連接數的限制也是不必的了(HTTP1.1 的谷歌對統一域名併發請求最多支持 6個 持久連接)。

那麼咱們能夠根據實際狀況進行資源拆分,從而節省下載時間,無併發請求限制的狀況下,下載的時間是根據並行下載的最長時間來算的,無需等待上一個資源下載,才能進行另一個資源的下載,在資源比較多的狀況下,這將大大提高資源整體的下載速度。

之前的 CSS 的雪碧圖 優化手段,在多路複用的特性下,已是不必的了。

多路複用還帶來了,延遲低的優化,這也是速度提高的一方面。

二進制分幀

在應用層與傳輸層之間增長一個二進制分幀層,以此達到在不改動 HTTP 的語義,HTTP 方法、狀態碼、URI 及首部字段的狀況下,突破 HTTP1.1 的性能限制,改進傳輸性能,實現低延遲和高吞吐量。

在二進制分幀層上,HTTP2.0 會將全部傳輸的信息分割爲更小的消息和幀,並對它們採用二進制格式的編碼,其中HTTP1.x 的首部信息會被封裝到 Headers 幀,而咱們的 request body 則封裝到 Data 幀裏面。

首部字段壓縮

HTTP2.0 使用 **HPACK **算法對首部字段的數據進行壓縮,這樣數據體積小了,在網絡上傳輸就會更快。

首部字段差別傳輸

HTTP2.0 規定了在客戶端和服務器端會使用而且維護首部表來跟蹤和存儲以前發送的鍵值對,對於相同的頭部,沒必要再經過請求發送,只需發送一次。

事實上,若是請求中不包含首部字段(例如對同一資源的輪詢請求),此時服務器自動使用以前請求發送的首部字段,那麼首部字段開銷就是零字節。

若是首部發生變化了,那麼只須要發送變化了數據在 Headers 幀裏面,新增或修改的首部幀會被追加到首部表首部表在 HTTP2.0 的鏈接存在期內始終存在,由客戶端和服務器共同漸進地更新。

使用 CDN

嚴格意義上,CDN 不算 Http 優化,前端也沒法直接處理這個事情,這是運維的事。CDN 節點能夠解決跨運營商和跨地域訪問的問題,提高訪問速度。

CDN的全稱是 Content Delivery Network,即內容分發網絡。CDN 是構建在網絡之上的內容分發網絡,依靠部署在各地的邊緣服務器,經過中心平臺的負載均衡、內容分發、調度等功能模塊,使用戶就近獲取所需內容,下降網絡擁塞,提升用戶訪問響應速度和命中率。CDN 的關鍵技術主要有內容存儲和分發技術。—— 科學百科

CDN 有什麼優點?

CDN 最大的優點在於提高用戶資源訪問速度,所以靜態資源走 CDN 是一個很好的優化點。 分佈式服務器,用戶就近訪問,CDN 節點能夠解決跨運營商和跨地域訪問的問題,同時分散源服務器訪問壓力。

還有一個而外的優勢: 無 cookie 傳輸(其實這個不徹底算是優點)。靜態資源通常無需 cookie,靜態資源放在不一樣域名能夠減小必定程度的帶寬和提高必定的訪問速度,雖然單個請求不明顯,可是量多了是會有質的區別的。

CDN 是如何分散源服務器的壓力的?

CDN 的核心點有兩個: 一個是緩存,一個是回源。

經過緩存和回源策略,達到分散源服務器的壓力。首先將從根服務器請求來的資源按要求緩存。而後當有用戶訪問某個資源的時候,若是被解析到的那個 CDN 節點沒有緩存響應的內容,或者是緩存已經到期,就會回源站去獲取。

相關文章
相關標籤/搜索