Webpack分包策略

在 webpack 打包過程中,經常出現(xiàn) vendor.js, app.js 單個文件較大的情況,這偏偏又是網頁最先加載的文件,這就會使得加載時間過長,從而使得白屏時間過長,影響用戶體驗。所以我們需要有合理的分包策略。

CommonsChunkPlugin

在 Webapck4.x 版本之前,我們都是使用 CommonsChunkPlugin 去做分離

<pre data-language="javascript" id="L4z5I" class="ne-codeblock" style="border: 1px solid #e8e8e8; border-radius: 2px; background: #f9f9f9; padding: 16px; font-size: 13px; color: #595959">plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    minChunks: function (module, count) {
      return (
        module.resource &&
        /\.js$/.test(module.resource) &&
        module.resource.indexOf(path.join(__dirname, './node_modules')) === 0
      )
    },
  }),
  new webpack.optimize.CommonsChunkPlugin({
    name: 'common',
    chunks: 'initial',
    minChunks: 2,
  }),
]</pre>

我們把以下文件單獨抽離出來打包

  • node_modules 文件夾下的,模塊
  • 被 3 個 入口 chunk 共享的模塊

optimization.splitChunks

webpack 4 最大的改動就是廢除了 CommonsChunkPlugin 引入了 optimization.splitChunks。如果你的 mode 是 production,那么 webpack4 就會自動開啟 Code Splitting。

它內置的代碼分割策略是這樣的:

  • 新的 chunk 是否被共享或者是來自 node_modules 的模塊

  • 新的 chunk 體積在壓縮之前是否大于 30kb

  • 按需加載 chunk 的并發(fā)請求數量小于等于 5 個

  • 頁面初始加載時的并發(fā)請求數量小于等于 3 個

雖然在 webpack4 會自動開啟 Code Splitting,但是隨著項目工程的最大,這往往不能滿足我們的需求,我們需要再進行個性化的優(yōu)化。

應用實例

我們先找到一個優(yōu)化空間較大的項目來進行操作。這是一個后臺管理系統(tǒng)項目,大部分內容由 3-4 個前端開發(fā),平時開發(fā)周期較短,且大部分人沒有優(yōu)化意識,只是寫好業(yè)務代碼完成需求,日子一長,造成打包出來的文件較大,大大影響性能。

我們先用 webpack-bundle-analyzer 分析打包后的模塊依賴及文件大小,確定優(yōu)化的方向在哪。

image

然后我們再看下打包出來的 js 文件

image

看到這兩張圖的時候,我內心是崩潰的,槽點如下

  • 打包后生成多個將近 1M 的 js 文件,其中不乏 vendor.js 首頁必須加載的大文件

  • xlsx.js 這樣的插件沒必要使用,導出 excel 更好的方法應該是后端返回文件流格式給前端處理

  • echart 和 iview 文件太大,應該使用 cdn 引入的方法

吐槽完之后我們就要開始做正事了。正是因為有這么多槽點,我們才更好用來驗證我們優(yōu)化方法的可行性。

抽離 echart 和 iview

由上面分析可知,echart 和 iview 文件太大,此時我們就用到 webpack4 的 optimization.splitChunks 進行代碼分割了,把他們單獨抽離打包成文件。(為了更好地呈現(xiàn)優(yōu)化效果,我們先把 xlsx.js 去掉)

vue.config.js 修改如下:

<pre data-language="javascript" id="uP8eu" class="ne-codeblock" style="border: 1px solid #e8e8e8; border-radius: 2px; background: #f9f9f9; padding: 16px; font-size: 13px; color: #595959">chainWebpack: config => {
    config.optimization.splitChunks({
      chunks: 'all',
      cacheGroups: {
        vendors: {
          name: 'chunk-vendors',
          test: /[\\/]node_modules[\\/]/,
          priority: 10,
          chunks: 'initial'
        },
        iview: {
          name: 'chunk-iview',
          priority: 20,
          test: /[\\/]node_modules[\\/]_?iview(.*)/
        },
        echarts: {
          name: 'chunk-echarts',
          priority: 20,
          test: /[\\/]node_modules[\\/]_?echarts(.*)/
        },
        commons: {
          name: 'chunk-commons',
          minChunks: 2,
          priority: 5,
          chunks: 'initial',
          reuseExistingChunk: true
        }
      }
    })
  },
 </pre>

此時我們再用 webpack-bundle-analyzer 分析一下

[圖片上傳中...(image-3a07ae-1626658031151-3)]

打包出來的 js 文件

[圖片上傳中...(image-a0cc41-1626658031151-2)]

從這里可以看出我們已經成功把 echart 和 iview 單獨抽離出來了,同時 vendor.js 也相應地減小了體積。此外,我們還可以繼續(xù)抽離其他更多的第三方模塊。

CDN 方式

雖然第三方模塊是單獨抽離出來了,但是在首頁或者相應路由加載時還是要加載這樣一個幾百 kb 的文件,還是不利于性能優(yōu)化的。這時,我們可以用 CDN 的方式引入這樣插件或者 UI 組件庫。

  1. index.html 引入相應 cdn 鏈接
<head>  <link rel="stylesheet"  /></head><body>  <div id="app"></div>  <script src="https://cdn.bootcss.com/vue/2.6.8/vue.min.js"></script>  <script src="https://cdn.bootcdn.net/ajax/libs/iview/3.5.4/iview.min.js"></script>  <script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.16.8/xlsx.mini.min.js"></script>  <script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.16.8/cpexcel.min.js"></script></body>
  1. vue.config.js 配置 externals
configureWebpack: (config) => {  config.externals = {    vue: 'Vue',    xlsx: 'XLSX',    iview: 'iView',    iView: 'ViewUI',  }}
  1. 刪除之前的引入方式并卸載相應 npm 依賴包
npm uninstall vue iview echarts xlsx --save

此時我們在來看一下打包后的情況

image

打包出來的 js 文件

image

well done ! 這時基本沒有打包出大文件了,首頁加載需要的 vendor.js 也只有幾十 kb,而且我們還可以進一步優(yōu)化,就是把 vue 全家桶的一些模塊再通過 cdn 的方法引入,比如 vue-router,vuex,axios 等。這時頁面特別是首頁加載的性能就得到大大地優(yōu)化了。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容