得物技術淺談JS資源分包

背景

在版本更新迭代、新代碼上線後,若是用戶須要從新從服務器加載所有資源(js、css),確定會讓頁面打開變慢,這實際上是沒有必要的。css

爲了優化用戶體驗,提升頁面打開速度,能夠將js拆分紅多個模塊,每次有更新,用戶只須要加載更新了的業務代碼便可,這就是分包。html

方案

通常來講,前端項目無論框架是什麼,大可能是基於webpack打包的,好比umi、next、nuxt、vue-cli,因此本文只基於webpack打包工具給出方案。前端

webpack4提供了 splitChunks 插件,就是用來作代碼分割的,具體使用方法能夠查看官方文檔。vue

比較廣泛的分包策略是按照體積大小、共用率、更新頻率從新劃分咱們的包,使其儘量的利用瀏覽器緩存。node

根據這一策略給出通用的分包方案,將js拆分紅如下三個模塊:webpack

  1. 第三方依賴(node_modules)
  2. UI庫(antd、element-ui、cube-ui)
  3. 業務代碼

所以,每次發佈代碼以後一般須要更新的只有三、而1和2直接從瀏覽器緩存中讀取便可。git

實施

以phoenix項目爲例,目前的線上頁面打包後的狀況以下圖:
1583408562565-f7e33c97-b848-43f0-8f36-7ac3642714ee.jpeg
經過分析工具看看各個模塊是什麼:
1583408824138-8c384490-cb1a-4760-8391-384477f110fa.jpeggithub

  • umi.js:框架js
  • verdors.async.js:第三方依賴
  • layouts_index.async.js和p_discountDetail_index.async.js:業務代碼
  • (忽略bundle.min.js,這是sentry腳本)

在什麼都不作的狀況下umi其實已經默認分包了,這是由於其內置的webpack提供了默認分包策略:web

  • 新的 chunk 是否被共享或者是來自 node_modules 的模塊
  • 新的 chunk 體積在壓縮以前是否大於 30kb
  • 按需加載 chunk 的併發請求數量小於等於 5 個
  • 頁面初始加載時的併發請求數量小於等於 3 個

使用上述方案對默認分包策略進行優化,將UI庫提取出來,在配置文件(umirc.ts)中加入自定義分包代碼:vue-cli

config.optimization.splitChunks({
  chunks: 'async',
  minSize: 30000,
  maxSize: 0,
  minChunks: 1,
  maxAsyncRequests: 5,
  maxInitialRequests: 3,
  automaticNameDelimiter: '~',
  name: true,
  cacheGroups: {
      vendors: {
        name: 'vendors',
      test: /[\\/]node_modules[\\/]/,
        priority: -10,
        },
    antdesigns: {
      name: 'antdesigns',
      test: /[\\/]node_modules[\\/]antd-mobile[\\/]/,
      priority: -9,
        }
  }
})

各個字段的表示的含義再也不此贅述,可查看官方文檔。主要看cacheGroups,把antd提取了出來。

再來看下打包以後的效果:
1583409592813-c2e019fc-bb1a-48e0-88b3-1ca36f23d5ff.jpeg

1583409982908-74aa9f75-aca3-45e7-861e-3aeab3da38fc.jpeg
多了一個antdesigns.js,成功將antd提取出來。

Q:其實這裏能夠思考一下,將antd提取到底合不合適?

A:phoenix項目是個多頁面應用,目前頁面數量很少,而antd也支持按需引入,將antd代碼打包進各個頁面的業務代碼或者node_modules中也不會增長多少體積,而antd代碼體積並不大,單獨提取出來後須要多一次http連接,感受沒有必要。不過隨着之後項目體積變大,也就不必定了。因此各個項目仍是要根據自身狀況進行分包。

結論

分包是一個博弈的過程,是讓 a bundle 大一點仍是 b?

是讓首次加載快一點仍是讓 cache 的利用率高一點?

但有一點要切記,拆包的時候不要過度的追求顆粒化,什麼都單獨的打成一個 bundle,否則你一個頁面可能須要加載十幾個js文件,若是你還不是HTTP/2的狀況下,請求的阻塞仍是很明顯的(受限於瀏覽器併發請求數)。

因此仍是那句話資源的加載策略並沒什麼徹底的方案,都須要根據項目自身狀況進行分包。

後續要作的

分包以後的下一步就是充分使用瀏覽器緩存,首先須要把靜態資源放到cdn上,再設置合理的緩存策略,只要chunk的hash沒有改變,都從瀏覽器緩存讀取。

參考資料:https://panjiachen.github.io/...

文/小辰

關注得物技術,攜手走向技術的雲端

相關文章
相關標籤/搜索