媒介
我们清晰,在 webpack
中经由过程CommonsChunkPlugin
能够将 entry
的进口文件中援用屡次的文件抽离打包成一个公用文件,从而削减代码反复冗余
entry: {
main: './src/main.js',
user: './src/user.js'
},
......
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
filename: 'common.js',
minChunks: 2,
})
// 打包天生一个文件common.js ,包括main.js 和 user.js 中援用两次及以上的模块代码
那末题目来了,当运用了相似 vue-router
的代码支解+懒加载功用的时刻,每一个路由对应的.vue
文件中,配合援用了屡次的模块,要怎样抽离出代码支解模块的公用模块代码出来呢?
题目现实场景
举个栗子
// 懒加载路由文件 routes.js
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.js'
...
</script>
// page/index/Index.vue 用户页路由文件
<template>用户页</template>
<script>
import pub from 'script/public.js'
...
</script>
上述运用了vue-router
懒加载打包出来的 首页路由文件index.js
和 用户页文件userIndex.js
都邑包括一份 public.js
的代码,反复了。
那末题目就是,在代码支解的代码中,怎样自动抽离大众代码? 就像CommonsChunkPlugin
的结果一样,CommonsChunkPlugin
怎样在 code-splitting
的场景上运用呢 ?
解决计划
如题目所示,存在两个运用了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
签字模块
手动将一切共用的模块抽离在一个文件。
建立文件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对应,
filename: 'common.bundle.js', // 抽离大众文件
minChunks: Infinity,
})
如许,假如路由文件或其他模块运用到了 commons.js
中的模块,都不会反复加载代码,而是在common.bundle.js
中猎取。
计划二,CommonsChunkPlugin
设置 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.
可知,设置 children 为 true 能够将code-splitting的模块的依靠模块抽离到父模块,如许做的效果就是,确切抽离公用模块,降低了代码反复,削减了代码体积。然则同时,抽离到父模块,也意味着假如有一个懒加载的路由 ShopList.vue
没有用到public.js
模块,然则现实上引入了父模块,也为这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.
设置了async
, 会将上述懒加载的路由文件公用的模块代码,抽离打包成一个零丁的文件,而且该文件是按需加载的,假如某个路由没有运用到这些公用模块,是不会加载进来的。
举个例子:
首页路由模块(接见途径/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 情况下的公用模块抽离。
以下附上简朴的webpack.config.js
设置代码
entry: {
main: './src/main.js'
},
...
plugins: [
...
new webpack.optimize.CommonsChunkPlugin({
name: "main",
minChunks: 2,
children: true,
// deepChildren: true,
async: true,
})
]
The CommonsChunkPlugin has been removed in webpack v4 legato. To learn how chunks are treated in the latest version, check out the SplitChunksPlugin.
PS: webpack 4 已将
CommonsChunkPlugin
烧毁,解决计划仅能在webpack 3 以下运用。
参考资料
commons-chunk-plugin
CommonChunkPlugin: Feature – Select statically imported modules from chunks that were created from a dynamic import (require.ensure / System.import / import(“..”))