我知道,通過CommonsChunkPlugin
可以將 entry
的入口文件中引用多次的文件抽離打包成一個(gè)公用文件,從而減少代碼重復(fù)冗余
entry: {
main: './src/main.js',
user: './src/user.js'
},
......
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
filename: 'common.js',
minChunks: 2,
})
// 打包生成一個(gè)文件common.js ,包含main.js 和 user.js 中引用兩次及以上的模塊代碼
那么當(dāng)我使用了 vue-router
代碼分割 懶加載的時(shí)候,每個(gè)路由對(duì)應(yīng)的.vue
文件中,共同引用了多次的模塊,怎么自動(dòng)抽離出來。
懶加載路由文件
const
Index = () => import(/* webpackChunkName: "index" */ "page/index/Index.vue"),
User = () => import(/* webpackChunkName: "userIndex" */ "page/user/Index.vue"),
UserDetail = () => import(/* webpackChunkName: "userDetail" */ "page/user/Detail.vue"),
...
// page/index/Index.vue 首頁路由文件
<template>首頁</template>
<script>
import pub from 'script/public'
...
</script>
// 用戶頁
// page/index/Index.vue 用戶頁路由文件
<template>用戶頁</template>
<script>
import pub from 'script/public'
...
</script>
上述使用了vue-router
懶加載打包出來的 首頁路由文件index.js
和 用戶頁文件userIndex.js
都會(huì)包含一份 public.js
的代碼,重復(fù)了。
我的問題就是,在代碼分割的代碼中,怎么自動(dòng)抽離公共代碼? 就像CommonsChunkPlugin
的效果一樣,或者說CommonsChunkPlugin
怎么在 code-splitting
的場(chǎng)景上使用?
如問題所示,存在兩個(gè)使用了webpack code-splitting 和 懶加載的路由文件,路由文件都使用了公用的public.js
模塊。
// page/index/Index.vue 首頁路由文件
<template>首頁</template>
<script>
import pub from 'script/public'
...
</script>
// 用戶頁
// page/index/Index.vue 用戶頁路由文件
<template>用戶頁</template>
<script>
import pub from 'script/public'
...
</script>
要將 public.js
公用模塊抽離,有兩種解決方案
CommonsChunkPlugin
具名模塊手動(dòng)將所有共用的模塊抽離在一個(gè)文件。
創(chuàng)建文件commons.js
// commons.js
import pub from 'public'
在webpack.config.js
的CommonsChunkPlugin
插件指定commons
的entry
// webpack.config.js
entry:{
main: 'src/main.js',
commons: 'src/commons.js'
},
...
new webpack.optimize.CommonsChunkPlugin({
name: "commons", // 和 entry的commons對(duì)應(yīng),
filename: 'common.bundle.js', // 抽離公共文件
minChunks: Infinity,
})
這樣,如果路由文件或其他模塊使用到了 commons.js
中的模塊,都不會(huì)重復(fù)加載代碼,而是在common.bundle.js
中獲取。
CommonsChunkPlugin
設(shè)置 children
屬性官方文檔CommonsChunkPlugin 中 children屬性解釋
Move common modules into the parent chunk
With Code Splitting, multiple child chunks of an entry chunk can have common dependencies. To prevent duplication these can be moved into the parent. This reduces overall size, but does have a negative effect on the initial load time. If it is expected that users will need to download many sibling chunks, i.e. children of the entry chunk, then this should improve load time overall.
可知,設(shè)置 children 為 true 可以將code-splitting的模塊的依賴模塊抽離到父模塊,這樣做的后果就是,確實(shí)抽離公用模塊,降低了代碼重復(fù),減少了代碼體積。但是同時(shí),抽離到父模塊,也意味著如果有一個(gè)懶加載的路由 ShopList.vue
沒有用到public.js
模塊,但是實(shí)際上引入了父模塊,也為這ShopList.vue
也引入了public.js
的代碼。
這就需要CommonsChunkPlugin
的 async
屬性。
children
與 async
雙管齊下Extra async commons chunk
Similar to the above one, but instead of moving common modules into the parent (which increases initial load time) a new async-loaded additional commons chunk is used. This is automatically downloaded in parallel when the additional chunk is downloaded.
設(shè)置了async
, 會(huì)將上述懶加載的路由文件公用的模塊代碼,抽離打包成一個(gè)單獨(dú)的文件,并且該文件是按需加載的,如果某個(gè)路由沒有使用到這些公用模塊,是不會(huì)加載進(jìn)來的。
舉個(gè)例子:
首頁路由模塊(訪問路徑/index
),引用了 public
模塊
用戶路由模塊(訪問路徑/user
),引用了 public
模塊
購物車模塊(訪問路徑/shop
),沒有引用 public
模塊
那么,打包生成的文件大概是
main.js - 根入口文件
index.js - 首頁路由文件
user.js - 用戶路由文件
shop.js - 購物車路由文件
0.js - 抽離路由的公用模塊文件
訪問url/index
,加載的依賴文件是main.js + index.js + 0.js
訪問url/user
,加載的依賴文件是main.js + user.js + 0.js
訪問url/shop
,加載的依賴文件是main.js + shop.js
基本解決了 lazy load + code-splitting 情況下的公用模塊抽離。
以下附上簡(jiǎn)單的webpack.config.js
配置代碼
entry: {
main: './src/main.js'
},
...
plugins: [
...
new webpack.optimize.CommonsChunkPlugin({
name: "main",
minChunks: 2,
children: true,
// deepChildren: true,
async: true,
})
]
commons-chunk-plugin
CommonChunkPlugin: Feature - Select statically imported modules from chunks that were created from a dynamic import (require.ensure / System.import / import(".."))
標(biāo)準(zhǔn)的做法不敢說,但是有一個(gè)解決方法,就是把你的公共模塊當(dāng)成 vue
插件注進(jìn)去
假設(shè)注入成這樣
Vue.prototype.$test= {test1: () => console.log(1), test2: () => console.log(2)}
然后你就可以在任意地方用 this.$test.test1()
this.$test.test2()
使用
這樣最后每個(gè)單獨(dú)的文件不會(huì)包括上面的公用方法,公用方法會(huì)被扔到那個(gè)全局 app.js里面
補(bǔ)充疑問
假設(shè)入口文件如下
打包生成的文件
這么做 vendor.**.js
一般是不會(huì)變的,如果按你后來的解決方案,懶加載路由使用的公用的文件是重新生成一個(gè)新文件還是補(bǔ)充到這個(gè)文件?如果是改變這個(gè)文件的話,我覺得不值得
因?yàn)樽约簩懙霉妙悗焓菚?huì)變的,每次都變動(dòng)加話,代價(jià)太大
繼續(xù)補(bǔ)充
新文檔看到了 children 跟 async 一起用是生成新的文件是吧,有機(jī)會(huì)試下
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
北大青鳥中博軟件學(xué)院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網(wǎng)學(xué)院和江蘇省首批服務(wù)外包人才培訓(xùn)基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團(tuán)創(chuàng)建于1999年,經(jīng)過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術(shù)與教育服務(wù)機(jī)構(gòu),發(fā)展為教育服務(wù)業(yè)的綜合性企業(yè)集團(tuán),成為集合面授教學(xué)培訓(xùn)、網(wǎng)
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國成功上市,融資1
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。