溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

splitChunks怎么分割降低包大小

發(fā)布時間:2022-09-20 15:38:53 來源:億速云 閱讀:266 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“splitChunks怎么分割降低包大小”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“splitChunks怎么分割降低包大小”吧!

    問題測驗

    講解開始之前,大家先看一個問題。如果你已經(jīng)知道問題的答案,而且明白為什么,就不必往下閱讀了。如果不知道答案或者知道答案,但不知道原因。那么,強烈建議閱讀本文。

    // webpack.config.js
    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    module.exports = {
      entry: { app: "./src/index.js" },
      output: {
        filename: "[name].js",
        path: path.resolve(__dirname, "dist")
      },
      optimization: {
        splitChunks: {
          chunks: "all"
        }
      },
      plugins: [
        new HtmlWebpackPlugin()
      ]
    };
    // index.js
    import "vue"
    import(/*webpackChunkName: 'a' */ "./a");
    import(/*webpackChunkName: 'b' */ "./b");
    // a.js
    import "vue-router";
    import "./someModule"; // 模塊大小大于30kb
    // b.js
    import "vuex";
    import "./someModule"; // 模塊大小大于30kb
    // someModule.js
    // 該模塊大小超過30kb
    // ...

    代碼分割的三種方式

    webpack 中以下三種常見的代碼分割方式:

    • 入口起點:使用 entry 配置手動地分離代碼。

    • 動態(tài)導(dǎo)入:通過模塊的內(nèi)聯(lián)函數(shù)調(diào)用來分離代碼。

    • 防止重復(fù):使用 splitChunks 去重和分離 chunk。 第一種方式,很簡單,只需要在 entry 里配置多個入口即可:

    entry: { app: "./index.js", app1: "./index1.js" }

    第二種方式,就是在代碼中自動將使用 import() 加載的模塊分離成獨立的包:

    //...
    import("./a");
    //...

    第三種方式,是使用 splitChunks 插件,配置分離規(guī)則,然后 webpack 自動將滿足規(guī)則的 chunk 分離。一切都是自動完成的。

    前兩種拆分方式,很容易理解。本文主要針對第三種方式進行討論。

    splitChunks 代碼拆分

    splitChunks 默認配置

    splitChunks: {
        // 表示選擇哪些 chunks 進行分割,可選值有:async,initial和all
        chunks: "async",
        // 表示新分離出的chunk必須大于等于minSize,默認為30000,約30kb。
        minSize: 30000,
        // 表示一個模塊至少應(yīng)被minChunks個chunk所包含才能分割。默認為1。
        minChunks: 1,
        // 表示按需加載文件時,并行請求的最大數(shù)目。默認為5。
        maxAsyncRequests: 5,
        // 表示加載入口文件時,并行請求的最大數(shù)目。默認為3。
        maxInitialRequests: 3,
        // 表示拆分出的chunk的名稱連接符。默認為~。如chunk~vendors.js
        automaticNameDelimiter: '~',
        // 設(shè)置chunk的文件名。默認為true。當為true時,splitChunks基于chunk和cacheGroups的key自動命名。
        name: true,
        // cacheGroups 下可以可以配置多個組,每個組根據(jù)test設(shè)置條件,符合test條件的模塊,就分配到該組。模塊可以被多個組引用,但最終會根據(jù)priority來決定打包到哪個組中。默認將所有來自 node_modules目錄的模塊打包至vendors組,將兩個以上的chunk所共享的模塊打包至default組。
        cacheGroups: {
            vendors: {
                test: /[\\/]node_modules[\\/]/,
                priority: -10
            },
            // 
        default: {
                minChunks: 2,
                priority: -20,
                reuseExistingChunk: true
            }
        }
    }

    以上配置,概括如下4個條件:

    • 模塊在代碼中被復(fù)用或者來自 node_modules 文件夾

    • 模塊的體積大于等于30kb(壓縮之前)

    • 當按需加載 chunks 時,并行請求的最大數(shù)量不能超過5

    • 初始頁面加載時,并行請求的最大數(shù)量不能超過將3

    // index.js
    import("./a");
    // ...
    // a.js
    import "vue";
    // ...

    以上代碼,在默認配置下的構(gòu)建結(jié)果如下:

    splitChunks怎么分割降低包大小

    原因分析

    • index.js 作為入口文件,屬于入口起點手動配置分割代碼的情況,因此會獨立打包。(app.js)

    • a.js 通過 import() 進行加載,屬于動態(tài)導(dǎo)入的情況,因此會獨立打出一個包。(1.js)

    • vue 來自 node_modules 目錄,并且大于30kb;將其從 a.js 拆出后,與 a.js 并行加載,并行加載的請求數(shù)為2,未超過默認的5;vue 拆分后,并行加載的入口文件并無增加,未超過默認的3。vue 也符合 splitChunks 的拆分條件,單獨打了一個包(2.js)

    理解 chunks

    chunks 用以告訴 splitChunks 的作用對象,其可選值有 async、 initialall。默認值是 async,也就是默認只選取異步加載的chunk進行代碼拆分。這個我們在開頭的例子里已經(jīng)驗證。這里我們通過兩個例子來看一下當chunks的值為 initialall 時,打包結(jié)果如何。 首先將chunks值改為 initial

    chunks: "initial"

    構(gòu)建結(jié)果如下:

    splitChunks怎么分割降低包大小

    原因分析:

    chunks 值為 initial 時,splitChunks 的作用范圍變成了非異步加載的初始 chunk,例如我們的 index.js 就是初始化的時候就存在的chunk。而 vue 模塊是在異步加載的chunk a.js 中引入的,所以并不會被分離出來。

    chunks 仍使用 initial, 我們對 index.jsa.js 稍作修改:

    // index.js
    import 'vue'
    import('./a')
    // a.js
    console.log('a')

    構(gòu)建結(jié)果如下:

    splitChunks怎么分割降低包大小

    原因分析:

    vueindex.js 直接被引入,而 index.js 是初始chunk,所以分離出來打到了 vendors~app.js 中。

    能不能讓 splitChunks 既處理初始chunk也處理異步chunk呢?答案是可以,只需要將 chunks 改為 all

    chunks: "all"

    index.jsa.js 稍作修改:

    // index.js
    import 'vue-router'
    import('./a')
    // a.js
    import 'vue'
    console.log('a')

    構(gòu)建結(jié)果如下:

    splitChunks怎么分割降低包大小

    原因分析:

    chunks 值為 all 時,splitChunks 的處理范圍包括了初始chunk和異步chunk兩種場景,因此 index.js 中的 vue-router 被分拆到了 vendors~app.js 中,而異步加載的chunk a.js 中的 vue 被分拆到了 3.js 中。推薦在開發(fā)中將 chunks 設(shè)置為 all。

    理解 maxInitialRequests

    maxIntialRequests 表示 splitChunks 在拆分chunk后,頁面中需要請求的初始chunk數(shù)量不超過指定的值。所謂初始chunk,指的是頁面渲染時,一開始就需要下載的js,區(qū)別于在頁面加載完成后,通過異步加載的js。

    splitChunks 做以下修改,其他使用默認配置:

    chunks: 'initial',
    maxInitialRequests: 1

    對 index.js 稍作修改:

    // index.js
    import 'vue'

    構(gòu)建結(jié)果如下:

    splitChunks怎么分割降低包大小

    原因分析:

    因為 maxInitialRequests 為1,如果 vueindex.js 中拆出的話,新創(chuàng)建的chunk作為初始chunk index.js 的前置依賴,是需要在頁面初始化的時候就先請求的。那么初始化時的請求數(shù)變成了2,因此不滿足拆分條件,所以 splitChunks 沒有對 index.js 進行拆分。

    理解 maxAsyncRequests

    maxInitialRequests 相對,maxAsyncRequests 表示 splitChunks 在拆分chunk后,并行加載的異步 chunk 數(shù)不超過指定的值。

    splitChunks 做以下修改,其他使用默認配置:

    maxAsyncRequests: 1

    index.js 稍作修改:

    // index.js
    import('./a')
    // a.js
    import 'vue'
    console.log('a')

    構(gòu)建結(jié)果如下:

    splitChunks怎么分割降低包大小

    原因分析: 因為 maxAsyncRequests 為1,由于 a.js 是通過 import() 異步加載的,此時并行的異步請求數(shù)是1。如果將 vuea.js 中拆出的話,拆出的包也將成為一個異步請求chunk。這樣的話,當異步請求 a.js 的時候,并行請求數(shù)有2個。因此,不滿足拆分條件,所以 splitChunks 沒有對 a.js 進行拆分。

    理解 minChunks

    minChunks 表示一個模塊至少應(yīng)被指定個數(shù)的 chunk 所共享才能分割。默認為1。

    splitChunks 做以下修改,其他使用默認配置:

    chunks: 'all',
    minChunks: 2

    index.js 稍作修改:

    // index.js
    import 'vue'

    構(gòu)建結(jié)果如下:

    splitChunks怎么分割降低包大小

    原因分析:

    因為 minChunks 為 2,所以只有當 vue 至少被2個 chunk 所共享時,才會被拆分出來。

    思考題

    請問如下代碼,構(gòu)建結(jié)果是什么?

    chunks: 'all',
    minChunks: 2
    // index.js
    import 'vue'
    import './a'
    // a.js
    import 'vue'
    console.log('a')

    理解 cache groups

    cacheGroups 繼承 splitChunks 里的所有屬性的值,如 chunks、minSizeminChunks、maxAsyncRequestsmaxInitialRequests、automaticNameDelimitername ,我們還可以在 cacheGroups 中重新賦值,覆蓋 splitChunks 的值。另外,還有一些屬性只能在 cacheGroups 中使用:test、priority 、reuseExistingChunk

    通過 cacheGroups,我們可以定義自定義 chunk 組,通過 test 條件對模塊進行過濾,符合條件的模塊分配到相同的組。

    cacheGroups 有兩個默認的組,一個是 vendors,將所有來自 node_modules 目錄的模塊;一個 default,包含了由兩個以上的 chunk 所共享的模塊。

    前面的例子中,你可能注意到了怎么有的拆分出的chunk名字這么奇怪,例如 vendors~app(默認由 cacheGroups 中組的 key + 源chunk名組成)。我們看一下如何自定義拆分出的chunk名。

    首先找到該chunk所屬的分組,該例為 vendors 分組,作如下修改,其他使用默認配置:

    chunks:'all',
    cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: "customName",
          priority: -10
        }
    }

    對 index.js 稍作修改:

    // index.js
    import 'vue'

    構(gòu)建結(jié)果如下:

    splitChunks怎么分割降低包大小

    原因分析:

    vue 來自 node_modules 目錄,被分配到了默認的 vendors 組中,如果不指定 name 的話,會使用默認的chunk名,這里我們指定了 name,因此最終的chunk名為customName。

    模塊還可以分配到多個不同的組,但最終會根據(jù) priority 優(yōu)先級決定打包到哪個 chunk。

    新增一個分組:

    chunks:'all',
    cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: "customName",
          priority: -10
        },
        customGroup: {
          test: /[\\/]node_modules[\\/]/,
          name: "customName1",
          priority: 0
        }
    }

    構(gòu)建結(jié)果:

    splitChunks怎么分割降低包大小

    原因分析:

    雖然 vendorscustomGroup 這個兩個組的條件都符合,但由于后者的優(yōu)先級更高,所以最終將 vue 打包到了 customName1.js 中。

    到此,相信大家對“splitChunks怎么分割降低包大小”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問一下細節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI