載入速度優化專項 > 體積優化分享

linong發表於2022-02-08

載入速度優化專項 > 體積優化分享

說到載入速度優化我們能想到什麼?網上能找到一些什麼內容?CDN? GZIP? 開啟快取?HTTP2? Tree-shaking?

這些內容對嗎?不全對!接下來我們針對性的分析一下。

網路、載入速度優化

  1. 為什麼我說 CDN 可以提速不全對?脫離劑量談毒性,都是耍流氓(這裡指脫離環境一把梭哈不現實)
    CDN 是指是什麼?

    CDN 的全稱是 Content Delivery Network,即內容分發網路。CDN 是構建在現有網路基礎之上的智慧虛擬網路,依靠部署在各地的邊緣伺服器,通過中心平臺的負載均衡、內容分發、排程等功能模組,使使用者就近獲取所需內容,降低網路擁塞,提高使用者訪問響應速度和命中率。CDN 的關鍵技術主要有內容儲存和分發技術。
    1. 如果你的 CDN 本身節點比較少,並沒有覆蓋全面,那麼並不會提速。(比如說你買的這個 CDN 沒有海外節點,但是你想提升海外節點的訪問速度)
    2. 如果你的 CDN 是外網的,而你的專案是內網,那麼速度反而會更慢。(內網的距離比較近,所以速度快,內網頻寬足,所以速度快)
    3. 你的 CDN 是否可以承載你的請求量級?(比如說目前各大廠子都在自研自己的雲服務,阿里雲、騰訊雲)
  2. 開啟 GZIP 真的提速了嗎?是的真的提速了。但是一般伺服器早都開啟了。
    是沒有損耗的嘛?有損耗每個檔案都會計算 gzip,且無快取。可以手動生成對應的 gz 檔案。
  3. 開啟快取?無腦快取?看來你是沒有被 ios 支配過。
    一般來說快取也都是開啟狀態。我們目前一般的方案是 html 檔案無快取,js、css 強快取 hash 控制。
  4. HTTP2 真的是救星嘛?一般情況下是的,支援多路複用(突破六個連結限制,比如說有慢介面,大檔案),頭部壓縮。
    但是在高延遲的情況下,HTTP2 反而會更慢
  5. 有線 vs 無線(WIFI、4G),服務商對於網路有影響嘛?只有外網專案受影響嘛?

    1. 外網。服務商對於網路是有影響的,比如我家就是移動,ping 部分 ip 丟包嚴重,光纖和 4G 都是如此。使用聯通 4G 就什麼問題都沒有。
    2. 內網。這裡推薦使用有線,比較穩定。這裡分為兩個場景:

      1. 公司,一般都是 AP 皮膚。但是有時候 AP 節點就是換不過來,偶爾網路波動。再看 P90 的資料的時候就特別難看。
      2. 家裡,一般都是單個路由器。你可以參考在訊號強時,和訊號弱時比對載入速度。

體積優化

  1. Tree-shaking。好像有了 Tree-shaking 就完事大吉了。

    1. 但是在 webpack4 以後就是預設開啟的了。(yarn serve 不優化, yarn build 優化,內部通過環境變數控制的)
    2. Tree-shaking 只對 ES Module 起作用,對於 commonjs 無效,對於 umd 亦無效。
    3. 如果你的三方包不支援,那麼就不支援。所以這裡需要更新你包的版本,支援 按需 和 tree-shaking
  2. 依賴共享。

    1. 比如說我們寫了一個 Request 庫,裡面用了 axios。然後我們還有個訊息中心的庫,裡面也用了 axios。這個時候輸出的包裡面會有兩個 axios。
      這裡我們用的是(monorepo Lerna yarn)+ (config.externals)實現依賴共享,只載入一份 axios。
    2. 還有一個情況是我們使用了按需元件庫。但是主專案並沒有按需,而是全量匯入,導致載入了兩遍 element-ui。解決辦法就是主專案改成全量按需。

      [
       'component',
       {
       "libraryName": "element-ui",
       "styleLibraryName": "theme-chalk"
       },
       'element-ui',
      ],
  3. 分包。 對於不需要的資源延時載入、非同步載入。比如說有個流程中心,在你審批的時候同步載入了幾千個流程。但是你只需要使用其中一個。

    1. vue 元件支援非同步載入。當元件真的渲染的時候再去載入。

      Vue.component('async-example', function (resolve, reject) {
          setTimeout(function () {
              // 向 `resolve` 回撥傳遞元件定義
              resolve({
                  template: '<div>I am async!</div>'
              })
          }, 1000)
      })
      Vue.component(
          'async-webpack-example',
          // 這個動態匯入會返回一個 `Promise` 物件。
          () => import('./my-async-component')
      )
    2. 對於大依賴( xlsx.js、echarts)或者其他不著急的資源也可以非同步載入

      injectFn() {
          if (this.injected) {return;}
          this.injected = true;
          if (this.useBuiltIn && this.username && this.Prop) {
              import('../../../inject.js').then(({ inject }) => {
                  inject(this.Prop!, this.username);
              });
          }
      }
    3. 合包。也不能拆太細,平白提高了 QPS。

      1. 什麼叫壓縮?說白了就是相同和合並,比如說 '11111111111111111111' 改成 '1'.repeat(20)

        內容壓縮很簡單,它就是移除多餘的空白字元,插入單個的重複字元指出一個字串中重複的字元,以及將小型的位串用頻繁使用的字元替代。這種型別的壓縮能夠將文字檔案的大小減少50%。壓縮由使用特定公式和演算法的程式來執行,它確定如何壓縮和解壓資料。
        gzip 使用deflate演算法進行壓縮。gzip 對於要壓縮的檔案,首先使用LZ77演算法的一個變種進行壓縮,對得到的結果再使用Huffman編碼的方法
  4. 合理的 babel 處理。比如說你的內網專案,那麼可以只支援較高版本的瀏覽器,減少 babel 和 polyfill。

    # 你知道這代表了什麼?
    > 1%
    last 2 versions # 表示將會支援 IE10 & IE11

邏輯優化

減少序列程式碼。

  1. Promise.all 代替 axios().then(() => axios())
  2. axios1 = axios();axios2 = axios();await Promise.all(axios1,axios2); 代替 await axios();await axios();

總結

優化之路,相輔相成。

  1. 優化網路,可以更快載入,也就可以更快執行。
  2. 優化併發不阻塞,並行載入,也可以更快執行。
  3. 優化體積,更小的體積,更高的複用,這樣就可以使用更少的頻寬,同樣可以更快的執行
  4. 使用快取,更低的 QPS,提前做 DNS 解析。也可以讓載入更快。

專案實戰

我提供了一些最簡案例在倉庫中:Demo 倉庫地址,你只需要看例子就可以直接看到問題(然後你可以去優化它)。

比如說:
image.png

分析手段

Chrome DevTools Lighthouse

這裡可以給我們的頁面打分,也會給出優化建議。如果能把這裡的點都優化了,那麼你的頁面載入就會起飛。

  1. 我們看看思否首頁,這分就挺高了。不過他們這個是靜態直出肯定會好很多,一般慢的都是後臺中臺 vue、react、單頁應用、巨石應用。
    image.png
  2. 我們再看看掘金首頁,這個分就差點事了,可以看到有一些優化建議。看了好像他們首頁資料好像是骨架,然後後面回來的資料。
    image.png
  3. 之前聽說 26 分,我也來看看。image.png

Chrome DevTools Network

這裡主要是看網路阻塞情況,比如說 http1.1 的時候是不是那個請求阻塞了你。

yarn build --report

這個主要是分析包體積的,我使用的工具也主要是這個。

比如說這個案例,你可以看到有多個 axios,然後每一個 axios 那哪裡引入的,這個時候你可以考慮通過 peerDependencies 還是 externals 來處理一下這樣的資源。

image.png

Chrome DevTools Performance

這個主要是分析程式碼執行效率的。

相關文章