一步一步的了解webpack4的splitChunk插件(小結(jié))
初衷
webpack4出了兩個(gè)月,發(fā)現(xiàn)大家包括我對(duì)splitChunk的使用都還是在摸索階段。我也看了挺多別人的配置demo,都覺得不太滿意或者沒得到太好的解惑,issue 下面的問題也沒什么人回復(fù),只能自己操作了,順便記錄下來,如果大家有更好的,歡迎評(píng)論區(qū)留下地址。
常用參數(shù)
- minSize(默認(rèn)是30000):形成一個(gè)新代碼塊最小的體積
- minChunks(默認(rèn)是1):在分割之前,這個(gè)代碼塊最小應(yīng)該被引用的次數(shù)(譯注:保證代碼塊復(fù)用性,默認(rèn)配置的策略是不需要多次引用也可以被分割)
- maxInitialRequests(默認(rèn)是3):一個(gè)入口最大的并行請(qǐng)求數(shù)
- maxAsyncRequests(默認(rèn)是5):按需加載時(shí)候最大的并行請(qǐng)求數(shù)。
- chunks (默認(rèn)是async) :initial、async和all
- test: 用于控制哪些模塊被這個(gè)緩存組匹配到。原封不動(dòng)傳遞出去的話,它默認(rèn)會(huì)選擇所有的模塊。可以傳遞的值類型:RegExp、String和Function
- name(打包的chunks的名字):字符串或者函數(shù)(函數(shù)可以根據(jù)條件自定義名字)
- priority :緩存組打包的先后優(yōu)先級(jí)。
如果你對(duì)這些配置還是不熟悉的話,一拉到底,看看文檔
正文
先總覽一下所有配置,后續(xù)會(huì)根據(jù)demo跑一遍常見的需求。
optimization: { splitChunks: { chunks: "async", // 必須三選一: "initial" | "all"(推薦) | "async" (默認(rèn)就是async) minSize: 30000, // 最小尺寸,30000 minChunks: 1, // 最小 chunk ,默認(rèn)1 maxAsyncRequests: 5, // 最大異步請(qǐng)求數(shù), 默認(rèn)5 maxInitialRequests : 3, // 最大初始化請(qǐng)求書,默認(rèn)3 automaticNameDelimiter: '~',// 打包分隔符 name: function(){}, // 打包后的名稱,此選項(xiàng)可接收 function cacheGroups:{ // 這里開始設(shè)置緩存的 chunks priority: 0, // 緩存組優(yōu)先級(jí) vendor: { // key 為entry中定義的 入口名稱 chunks: "initial", // 必須三選一: "initial" | "all" | "async"(默認(rèn)就是async) test: /react|lodash/, // 正則規(guī)則驗(yàn)證,如果符合就提取 chunk name: "vendor", // 要緩存的 分隔出來的 chunk 名稱 minSize: 30000, minChunks: 1, enforce: true, maxAsyncRequests: 5, // 最大異步請(qǐng)求數(shù), 默認(rèn)1 maxInitialRequests : 3, // 最大初始化請(qǐng)求書,默認(rèn)1 reuseExistingChunk: true // 可設(shè)置是否重用該chunk } } } },
接下來看看第一個(gè)例子
entry: { pageA: "./pageA", // 引用utility1.js utility2.js pageB: "./pageB", // 引用utility2.js utility3.js pageC: "./pageC" // 引用utility2.js utility3.js }, optimization: { splitChunks: { cacheGroups: { commons: { chunks: "initial", minChunks: 2, maxInitialRequests: 5, // The default limit is too small to showcase the effect minSize: 0 // This is example is too small to create commons chunks } } } },
結(jié)果如圖,一切都很正常 commons~pageA~pageB~pageC.js 文件就是utility2.js commons~pageB~pageC.js,根據(jù)上述代碼,這里的utility2被引用了三次,首先就被抽離了commons~pageA~pageB~pageC.js,然后utility3被引用了兩次就放到了commons~pageB~pageC.js,最后只剩下被引用一次的utility1.js,就直接放到了pageA.js里面,如果這里的utility1.js的也是兩次,他還是會(huì)新建一個(gè)chunk放進(jìn)去,而不是合并到commons~pageB~pageC.js,除非同入口引用才會(huì)合并。
mpageA.js pageB.js pageC.js
這里有個(gè)地方是需要優(yōu)化一下的,就是pageA.js pageB.js pageC.js的代碼不多,但是打出來的包很大,肯定是一些webpack的運(yùn)行文件,直接加上runtimeChunk
runtimeChunk: "single" // 等價(jià)于 runtimeChunk: { name: "manifest" }
現(xiàn)在就好了
引用第三方模塊 pageA引用vue.js pageB引用react react-dom
vendor: { test: /node_modules/, chunks: "initial", name: "vendor", priority: 10, enforce: true }
但是,這樣子的話,會(huì)把pageA pageB pageC所有的庫都打包到一起vendor.js
假如我想拆分這個(gè)vendor.js為pageA-vendor.js pageB-vendor.js怎么辦,我試了很久,試出一個(gè)最簡(jiǎn)單的辦法,去掉手動(dòng)的vendor,讓插件自動(dòng)處理。
splitChunks: { chunks: "all", cacheGroups: { commons: { chunks: "initial", minChunks: 2, maxInitialRequests: 5, // The default limit is too small to showcase the effect minSize: 0 // This is example is too small to create commons chunks } } },
后來,我把webpack mode改成production后,發(fā)現(xiàn)不管用了,同樣的配置,在生產(chǎn)模式下,打包出來的東西有點(diǎn)匪夷所思,vendor-pageB.js被合并到了pageB.js里面了。
后來我折騰了好久也分析不出來為什么,自己折騰出來一種方式,還是老子手動(dòng)來吧,自動(dòng)化一邊去
commons: { chunks: "initial", minChunks: 2, maxInitialRequests: 5, // The default limit is too small to showcase the effect minSize: 0 // This is example is too small to create commons chunks }, 'vendor-pageA': { test: /vue/, // 直接使用 test 來做路徑匹配 chunks: "initial", name: "vendor-pageA", enforce: true, }, 'vendor-pageB': { test: /react/, // 直接使用 test 來做路徑匹配 chunks: "initial", name: "vendor-pageB", enforce: true, },
成功打包出來了自己想要的東西。
動(dòng)態(tài)引入
動(dòng)態(tài)引入大家應(yīng)該都不陌生,就是大家所說的懶加載,直接在pageA和pageB頁面里動(dòng)態(tài)引入common-async.js,在這里我先說說,splitChunk應(yīng)該是可以自動(dòng)化處理類似commonChunk里的async,child等情況的。
import(/* webpackChunkName: "common-async.js" */"./common-async").then(common => { console.log(common); })
還不錯(cuò),成功打包出來了
這時(shí)候再試試,在這個(gè)common-async.js里面在引入共同的代碼f.js,看看會(huì)不會(huì)重復(fù)打包
f.js成功的被抽離出來了,其他文件也沒有被重復(fù)打包,挺好的。
注意的地方
- cacheGroups 會(huì)繼承和覆蓋splitChunks的配置項(xiàng),但是test、priorty和reuseExistingChunk只能用于配置緩存組。。
- cacheGroups 里的每一項(xiàng)最好都要加上chunks參數(shù),不然可能打包不出來你想要的東西。
- minSize 默認(rèn)是30KB(注意這個(gè)體積是壓縮之前的)在小于30kb的情況下一定要設(shè)置一個(gè)值,否則也可能打包不出來你想要的東西,而且這東西要加在cacheGroups里面。
- priority 在某些情況下,還是挺有用的,可以設(shè)置打包c(diǎn)hunks的優(yōu)先級(jí)。
上面的例子里面配置了一個(gè)commons,這里的name可以自己設(shè)置,也可以不設(shè)置,我是沒設(shè)置的,你可以試試設(shè)置了是什么樣子的,然后你就會(huì)明白這個(gè)name其實(shí)在某些情況下還是不設(shè)置的比較好。
commons: { chunks: "initial", minChunks: 2, maxInitialRequests: 5, // The default limit is too small to showcase the effect minSize: 0 , name: "commons" },
源碼
參考文章
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript解析機(jī)制與閉包原理實(shí)例詳解
這篇文章主要介紹了JavaScript解析機(jī)制與閉包原理,結(jié)合實(shí)例形式詳細(xì)分析了javascript解析機(jī)制相關(guān)概念、功能、用法以及閉包的原理、定義、使用方法,需要的朋友可以參考下2019-03-03js實(shí)現(xiàn)一維數(shù)組轉(zhuǎn)化為二維數(shù)組兩種簡(jiǎn)單方法
在日常開發(fā)中我們可能會(huì)遇到返回的數(shù)據(jù)不能直接使用,而數(shù)據(jù)提供者只給你傳遞二維數(shù)據(jù)格式的數(shù)據(jù),這個(gè)時(shí)候就需要我們做轉(zhuǎn)換,這篇文章主要給大家介紹了關(guān)于js實(shí)現(xiàn)一維數(shù)組轉(zhuǎn)化為二維數(shù)組的兩種簡(jiǎn)單方法,需要的朋友可以參考下2023-12-12用最通俗易懂的代碼幫助新手理解javascript閉包 推薦
我同樣也是個(gè)javascript新手,怎么說呢,先學(xué)的jquery,精通之后發(fā)現(xiàn)了javascript的重要性,再回過頭來學(xué)javascript面向?qū)ο缶幊?/div> 2012-03-03echarts橫向柱狀圖簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于echarts橫向柱狀圖簡(jiǎn)單實(shí)現(xiàn)的相關(guān)資料,ECharts是百度前端開發(fā)部開發(fā)的一個(gè)開源可視化庫,它可以幫助開發(fā)者輕松的實(shí)現(xiàn)各種數(shù)據(jù)可視化,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12最新評(píng)論