分包的好处

  1. 打包后有时会存在个别文件较大的情况, 这会导致依赖模块加载时变慢, 所以就需要将大的包分开
  2. 引入的模块通常没有改动, 改动多的是自己的代码, 可以把不会经常改动的部分单独分包出来, 避免每次打包所有的文件都会改动

(但是, 也不能分的太细, 分的越多浏览器需要发起的请求就越多, 会影响加载速度, 且会影响浏览器的缓存效率)

配置rollupOptions

export default defineConfig({
build: {
rollupOptions: {
output: {
// 分包要配置的内容是'vite.config.js'文件中`output`部分的内容
}
}
})

output中基本的配置选项

output: {
// 打包出来的文件的保存路径(默认保存在`dist`)
dir: "dist",
// 手动分包导入的模块文件
manualChunks: {
},
// 导入的模块文件的输出路径和命名规则
chunkFileNames: ,
// 资源文件的输出路径和命名规则
assetFileNames: ,
// 入口文件的输出路径和命名规则
entryFileNames: ,
}

manualChunks

我想把model_1模块和model_2模块打包成叫name的文件可以这么写

manualChunks: {
name: ['model_1', 'model_2'],
},

当然也可以单独打包成name_1name_2

manualChunks: {
name_1: ['model_1'],
name_2: ['model_2'],
},

将在node_modules文件夹里且被导入的模块打包

hint: manualChunks可以接受一个参数, 表示正在处理的模块的标识符(identifier), 通常是模块的路径, 下面例子里参数起的名字是id

打包成单个, 叫name的包

manualChunks(id) {
if (id.includes('node_modules')) {
return 'name';
}
},

hint: 参数id表示模块的路径, 这部分代码是将id中包含子字符串node_modules的模块全部打包到一个叫name的包(可能导致分出的包较大)

不同的模块单独打包

manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
},

hint: 通过字符串和数组操作, 将node_modules模块里面不同名字的包单独打包成相应名字的包(可能会导致分出的包较多)

分别打包module_1module_2其他的模块和入口文件打包

通过上面写的将不同的模块单独打包后发现module_1和module_2都比较大, 其他的都很小. 可以选择将module_1和module_2分别打包, 把其他小的和入口文件一起打包

manualChunks(id) {
if (id.includes('node_modules/module_1')) {
return 'name_1';
};
if (id.includes('node_modules/module_2')) {
return 'name_2';
}
},

hint: 将node_modules文件夹里的模块module_1打包成name_1, 模块module_2打包成name_2, 其他模块会打包到入口文件里面

chunkFileNames

将分好的包直接输出到相同路径下

这个[name].js中的[name]是特殊的占位符, 不是我举的例子, [name]会自动替换成动态导入的模块名称和上面手动分包自定义的文件名

chunkFileNames: 'static/js/[name].js',

hint: 将manualChunks里设定的打包出来的文件全部输出到static/js/路径里面

名字也可以弄成[name].[hash].js, [name]-[hash].js等,

增加的[hash]这个部分就是加文件指纹(项目构建内容有改动这个值就会变, 不改就不会变), [hash]用于浏览器的缓存控制, 因为项目变化文件名就会变化, 浏览器就会加载该文件, 让项目不受到浏览器缓存的影响, 显示最新的内容

中间加的'-', '.'相应的文件名字上[name]和[hash]之间会有'-', '.' 例如mname-374dije279ss.js, mname.fwjvh13diew.js之类的

根据包的路径和名称输出到不同路径下

可以像上面manualChunks(id)似的用函数声明的方法写, 这个例子用的是箭头函数声明的方法

chunkFileNames: (chunkInfo) => {
const facadeModuleId = chunkInfo.facadeModuleId ? chunkInfo.facadeModuleId.split('/') : [];
const fileName = facadeModuleId[facadeModuleId.length - 2] || '[name]';
return `js/${fileName}/[name].[hash].js`;
}

hint: facadeModuleId在Vite中是一个与分包文件相关的属性, 当一个模块是通过动态导入的方式加载的, Vite 会为这个模块创建一个分包, 并且将该模块的路径设置为, 分包对象.facadeModuleId(这个例子中给分包对象起名为chunkInfo)

assetFileNames

例1:

assetFileNames: (assetInfo) => {
// 可以根据文件类型定义不同的输出路径
if (assetInfo.name.endsWith('.png') || assetInfo.name.endsWith('.jpg')) {
return 'static/images/[name][extname]'; // 将图片放到 images 文件夹
}
if (assetInfo.name.endsWith('.css')) {
return 'static/css/[name][extname]'; // 将 CSS 文件放到 css 文件夹
}
// 默认的资源文件输出路径
return 'static/[name][extname]';
},

例2:

assetFileNames: 'static/[ext]/[name][extname]',

例3:

assetFileNames: 'static/[ext]/[name].[ext]',

hint: 在这个函数中[ext]为资源文件的扩展名, [extname]是'.'+资源文件的扩展名

例2和例3是等效的

entryFileNames

打包好的入口文件通常放在输出文件夹下的根目录

entryFileNames: '[name].js'

用Vite工具打包的其他优化方法

可以参考【VUE】vue3 vite项目打包优化 - 前端哥 (qianduange.cn)