SplitChunksPlugin簡介及在多入口頁項目中的實踐

SplitChunksPlugin是webpack4中官方plugin,用於做分包打包的,可以幫你把重複引入的模塊按規則打包到指定的js裏面。以下是SplitChunksPlugin的默認配置:

splitChunks: {
    chunks: "async", //在默認情況下,SplitChunksPlugin 僅僅影響按需加載的代碼塊,如果需要對同步的代碼做代碼分割打包,那麼chunk配置爲'all'
    minSize: 30000, // 模塊的最小體積
    minChunks: 1, // 模塊的最小被引用次數
    maxAsyncRequests: 5, // 按需加載的最大並行請求數
    maxInitialRequests: 3, // 一個入口最大並行請求數
    automaticNameDelimiter: '~', // 文件名的連接符
    name: true,
    cacheGroups: { // 緩存組
        vendors: {  //引入的node modules裏面的庫打包成一個vendor
            test: /[\\/]node_modules[\\/]/,
            priority: -10
        },
        default: {  //其他重複的模塊,如業務組件、自定義公共組件等
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true
        }
    }
}

在單一入口頁的項目開啓splitChunk的功能其實配置很簡單,只需要在 optimization 裏面配置如下,splitChunk會使用默認的配置對項目進行拆包

splitChunks: {
    chunks: 'all',
    name: true
}

一般我們配置多入口頁,都會使用 HtmlWebpackPlugin ,如果是 HtmlWebpackPlugin 結合SplitChunkPlugin 使用的話,需要在不同的入口頁面指明該頁面對應的chunk的名稱,否則該頁面引用的chunk文件對應不上的話,頁面是無法正常加載的

下圖是我的項目結構,app.js是主入口頁,其他幾個入口頁都是分享出去的頁面,對應app.js裏面的一些模塊(app.js裏面的模塊採取異步加載的方式引入)
在這裏插入圖片描述
如果不使用 SplitChunksPlugin ,我們利用 BundleAnalyzerPlugin 打包分析工具查看打包後的結果(下圖),非常大,很多公共的庫或業務組件被重複打包
在這裏插入圖片描述
接着,我們按SplitChunksPlugin的基礎配置,在webpack.config.js裏面引入,以~連接的chunk就是SplitChunksPlugin使用基礎的配置給我們拆包出來的文件,這時我們的頁面是不能正常加載的,因爲這些拆包出來的chunk不能自動地注入到所引用的入口頁裏
在這裏插入圖片描述
那麼我們先把項目裏引用的node_modules的三方庫拆出來,並在入口文件中注入,SplitChunksPlugin配置如下:

splitChunks: {
    chunks: 'all',
    name: true,
    cacheGroups: {
        vendors: { // 項目基本框架等
            chunks: 'all',
            test: /node_modules/,
            priority: 100,
            name: 'vendors',
        }
    }
}

HtmlWebpackPlugin配置:

new HtmlWebpackPlugin({
    template: './templete/index.html',
    filename: 'index.html',
    chunks: ['app', 'vendors']   //注入對應的入口js文件、拆包出來的verdor文件(命名跟SplitChunks cacheGroup裏配置的名稱一致)
}),
new HtmlWebpackPlugin({
    template: './templete/index-no-pb.html',
    filename: 'home.html',
    chunks: ['home', 'vendors']
}),
new HtmlWebpackPlugin({
    template: './templete/index-no-pb.html',
    filename: 'profile.html',
    chunks: ['profile', 'vendors']
}),
...

我們可以看到,除了公共庫的chunk,webpack還幫我們打包出了一些其他的公共chunk,這是因爲默認配置裏還有個default參數,會幫我們打包一些別的重複引用的模塊。同樣,我們還是需要給這些打包的chunk配置一下,不然這些公共chunk也不能被正常地注入
在這裏插入圖片描述
修改一下SplitChunksPlugin的配置

splitChunks: {
    chunks: 'all',
    name: true,
    cacheGroups: {
        vendors: { // 項目引用的三方庫,如mobx等
            chunks: 'all',
            test: /node_modules/,
            priority: 100,   //值越大,打包越優先參照此配置項
            name: 'vendors',
        },
        commons: { // 其他同步加載公共包,如自定義組件等
            chunks: 'all',
            minChunks: 2,
            priority: 80,
            name: 'commons'
            
        }
    }
}

重寫了splitChunks 的 cacheGroups 默認參數後,可以按照我們的要求進行打包了,node_modules裏面的部分打包到vendor.chunk裏面,自定義的組件等其他重複引用模塊被打包到了commons.chunk裏,注意在HtmlWebpackPlugin 裏面也要同時配置commons這個chunk
在這裏插入圖片描述
其實,按上面的配置,我們的打包結果已經比之前優化很多了,但是,這並不是最好的處理結果。因爲commons.chunk裏面打包的重複模塊,在不同的入口頁其實是用不上的。commons.chunk打包了所有引用超過兩次的模塊,其中就包括record chunk、profile chunk、home chunk、rank chunk等,因爲這些部分同時在app.js和對應的入口頁中引用了。比如說我只打開profile.html入口頁,那我只需要profile chunk,而不需要另外的一些模塊。那我們再修改一下配置

splitChunks: {
    chunks: 'all',
    name: true,
    cacheGroups: {
        vendors: { // 項目引用的三方庫,如mobx等
            chunks: 'all',
            test: /node_modules/,
            priority: 100,
            name: 'vendors',
        },
        commons: { // 其他同步加載公共包,如自定義組件等
            chunks: 'all',
            minChunks: 3,   //最小引用次數修改爲3,那麼app.js和其他入口頁共用的模塊就不會被打包進來,而是隻打包了引用次數超過三次的一些自定義組件
            name: 'commons',
            priority: 80,
        },
        default: false  //注意把cacheGroups的默認的default設置爲false,不然還是會走default裏面的配置,將引用了兩次以上的模塊進行打包
    }
}

最後結果如下圖所示,公共包有兩個,而業務邏輯模塊(home|rank|record|profile)沒有被打進commons.chunk裏面,被單獨打成了一個個異步chunk。

在這裏插入圖片描述

雖然最後的打包方式整體大小會比之前的稍大一點,但是在請求不同的入口頁時,會按需引入,以record.js入口頁爲例,請求時加載vendor + commons + record + recordChunk(約等於930多k),但是按之前的方式全部打到一個commons.chunk裏,請求時加載vendor + commons + record(約等於1019多k)

SplitChunksPlugin雖然好用,但是也不要盲目地使用,應該根據項目的具體情況而定,一般如果是單入口頁面,就直接按默認配置即可;多入口頁的話,可以根據具體情況再進行拆包,自己寫cacheGroups的配置的時候注意要關閉或者覆蓋默認配置。

【參考】

https://webpack.js.org/plugins/split-chunks-plugin/#defaults

https://www.jb51.net/article/151976.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章