通过配置rollup manualChunks
选项,实现webpack
的webpackChunkName
功能。
在rollup
中,为不同的模块指定相同的chunkName,就能将对应的内容编译到同一个包中。我们要做的就是,
首先在编译过程中,要转化webpackChunkName
配置的名称到模块id
中;
其次在编译结束时,要得到单个模块被哪些模块引用的信息;
最后在生成文件时,使用上述信息指定模块的chunkName
。
这一步在插件transform
方法中实现。例如路由文件内有如下内容:
const routes = [
{
path: '/detail/somepage',
component: () => import(/* webpackChunkName: "detail" */ '@/detail/somepage.vue'),
},
]
经过插件转化后,得到:
const routes = [
{
path: '/detail/somepage',
component: () => import('@/detail/somepage.vue?chunkName=detail'),
},
]
对于每个模块,要找到所有引用这个模块的模块名。即:
module/a -> module/b -> module/c
module/a -> module/d
显然,模块 a 被三个模块直接或间接依赖。最终我们可以得到如下数据:
{
"module/a": {chunkNames: ["c", "d"]},
"module/b": {chunkNames: ["c"]},
"module/c": {chunkNames: ["c"]},
"module/d": {chunkNames: ["d"]},
}
其中,chunkNames
保存的值c
、d
既为模块名字,也是最后生成文件的包名。
想要长效缓存,对于node_modules
和用户工作空间的代码,有不同的生成策略。具体可见nodeModuleId2issuerMap
和appModuleId2chunkNamesMap
函数。最后我们得到的数据如下:
const nodeModuleId2issuerMap = {
"E:/projects/hangban/webapp/node_modules/crypto-js/core.js": {chunkNames: ["crypto-js"]},
"E:/projects/hangban/webapp/node_modules/crypto-js/enc-base64.js": {chunkNames: ["crypto-js"]},
"E:/projects/hangban/webapp/node_modules/crypto-js/enc-base64url.js": {chunkNames: ["crypto-js"]},
......
"E:/projects/hangban/webapp/node_modules/echarts/lib/chart/bar.js": {chunkNames: ["echarts"]},
"E:/projects/hangban/webapp/node_modules/echarts/lib/chart/bar/BarView.js": {chunkNames: ["echarts"]},
"E:/projects/hangban/webapp/node_modules/echarts/lib/chart/bar/helper.js": {chunkNames: ["echarts"]},
......
}
const appModuleId2chunkNamesMap = {
"e:/projects/hangban/webapp/index.html": {chunkNames: ["main"]}
"e:/projects/hangban/webapp/src/boot/uid.ts": {chunkNames: ["main"]},
"e:/projects/hangban/webapp/src/projects/login/pages/bcm.vue?chunkName=login-bcm": {chunkNames: ["login-bcm"]},
"e:/projects/hangban/webapp/src/projects/login/pages/nbcb.vue?chunkName=login-nbcb": {chunkNames: ["login-nbcb"]},
"e:/projects/hangban/webapp/src/projects/login/pages/service.ts": {chunkNames: ["login-nbcb", "login-bcm"]},
......
}
为了长效缓存、减少包之间的耦合,制定了如下文件包生成策略(靠前优先):
- 从入口文件引入的三方模块,打包成 vendor
- 路由带有 webpackChunkName 的,按给定的名称打包
- 文件有且只有一次引用(入口文件或动态引入),按 rollup 默认逻辑
- 文件多次引用
- 如果是 node_modules 模块
- 若被单个包名引用,打入对应的包中
- 否则打入主包
- 如果是用户模块按照 getAppModuleChunkName 中的逻辑打包,即
- 如果被主包引用,打入主包
- 如果被单个包引用,打入对应的包中
- 如果被 2 个包引用,打入共享包中
- 其他情况,打入主包
- 如果是 node_modules 模块