优化前预览
目前无任何处理,打包文件大小约为4M
一、先安装rollup-plugin-visualizer
在项目根目录安装rollup-plugin-visualizer,此插件能图形化文件大小,方便观察
npm i -D rollup-plugin-visualizer
安装完在vite.config.ts中进行配置
import { visualizer } from 'rollup-plugin-visualizer'
// defineConfig配置项
plugins: [
visualizer({
emitFile: false,
filename: 'stats.html',
open: true,
sourcemap: true
})
]
保存配置后打包一次就能看见文件夹大小分布
二、解决大文件
一眼看去发现 china.json占比最大,先解决它。
看代码发现开发时是静态文件引入,修改为接口获取
修改为 ↓
改好后重新打包,一下子就小了不少
三、CDN引入第三方库
之前发现除了最大的静态JSON文件,第三方库占用空间也是非常大,所以下一步就是解决它。
在此之前需要安装 vite-plugin-cdn-import ,此插件可以帮我们使用CDN方式引入第三方库,减小请求压力,同时也缩小项目体积
npm i -D vite-plugin-cdn-import
安装好后再vite.config.ts文件中进行配置
import { autoComplete, Plugin as importToCDN } from "vite-plugin-cdn-import"
//放在 plugin 下
importToCDN({
modules: [
{
name: "element-plus",
var: "ElementPlus",
path: "https://unpkg.com/element-plus@2.4.2",
css: "https://unpkg.com/element-plus/dist/index.css"
},
autoComplete('axios'),
autoComplete('vue'),
autoComplete('moment'),
autoComplete('lodash'),
// {
// name: "vue",
// var: "Vue",
// path: "https://unpkg.com/vue@3.3.8"
// },
// {
// name: "moment",
// var: "Moment",
// path: "https://unpkg.com/moment@2.29.4"
// },
// {
// name: "lodash",
// var: "Lodash",
// path: "https://unpkg.com/lodash@4.17.21"
// },
],
}),
此处使用 autoComplete 可以自动帮助引入,目前只支持部分库,具体可以查看 vite-plugin-cdn-import配置文档, 其他函数不支持的需要自行配置path,推荐去 www.jsdelivr.com查找
举个栗子,假设我需要引入Element-plus,那么我可以搜索element-plus
点击进入
这里就有.js 以及配套的.css文件,将链接填入配置保存即可。
如果有版本需求 ,可以用unpkg.com/:package@:version/:file 方式引入,例如https://unpkg.com/vue@3.3.8
保存后再次打包
可以看到比上次小了近1M!
四、依赖分包
虽然咱们项目体积已经缩小了很多,但是可以从刚才打包后的文件里看出,存在个别文件相比其他的要大得多,这会导致依赖模块加载时变慢,所以我们下一步就是要将大包分开。
我们可以先去vite官网找到构建选项中的 build.rollupOptions ,vite其实是基于rollup为底层开发的,这里的配置更是可以直接参照rollup配置,这里我们配置部分选项,在vite.config.ts文件中添加以下配置项
// defineConfig 下
build: {
rollupOptions: {
output: {
sourcemap: true,
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
manualChunks(id){
// id为文件的绝对路径
if(id.includes('node_modules')){
return id.toString().split('node_modules/')[1].split('/')[0].toString()
}
}
}
}
}
保存后再次打包后可以看到之前的大文件已经被拆分开
五、gzip压缩
最后就是代码压缩了,依旧是安装插件vite-plugin-compression
npm i -D vite-plugin-compression
安装完再进行配置
import viteCompression from 'vite-plugin-compression'
plugin:[
viteCompression({
verbose: true,
disable: false,
threshold: 1024,
algorithm: 'gzip',
deleteOriginFile: true
})
]
保存再次打包,看看效果咋样
这里好像没有啥效果,可能是因为之前的代码已经被压缩了,具体效果可能会有不同。
总结
这几套组合拳打过去,项目体积不小也难,配置过程需要注意配置项位置,有时候配置好了没有效果可以去插件文档里检查下是否放错了位置。
============================================================================
这里贴一下配置代码以及最后结果
import { UserConfigExport, ConfigEnv, loadEnv } from 'vite'
import { viteMockServe } from 'vite-plugin-mock'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import DefineOptions from 'unplugin-vue-define-options/vite'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
import { visualizer } from 'rollup-plugin-visualizer'
import { autoComplete, Plugin as importToCDN } from "vite-plugin-cdn-import"
import viteCompression from 'vite-plugin-compression'
export default ({ command, mode }: ConfigEnv): UserConfigExport => {
let env = loadEnv(mode, process.cwd())
return {
plugins: [
vue(),
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
symbolId: 'icon-[dir]-[name]',
}),
VueSetupExtend(),
DefineOptions(),
viteMockServe({
mockPath: 'mock',
localEnabled: command === 'serve',
}),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
visualizer({
emitFile: false,
filename: 'stats.html',
open: true,
sourcemap: true
}),
importToCDN({
modules: [
autoComplete('axios'),
autoComplete('vue'),
autoComplete('moment'),
autoComplete('lodash'),
{
name: "element-plus",
var: "ElementPlus",
path: "https://unpkg.com/element-plus@2.4.2",
css: "https://unpkg.com/element-plus/dist/index.css"
},
{
name: 'pinia',
var: 'pinia',
path: "https://unpkg.com/pinia@2.1.7"
},
{
name: "echarts",
var: "echarts",
path: "https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"
},
{
name: "vue-router",
var: "vue-router",
path: "https://cdn.jsdelivr.net/npm/vue-router@4.2.5/dist/vue-router.global.min.js"
},
{
name: "echarts-liquidfill",
var: "echarts-liquidfill",
path: "https://cdn.jsdelivr.net/npm/echarts-liquidfill@3.1.0/dist/echarts-liquidfill.min.js"
},
],
}),
viteCompression({
verbose: true,
disable: false,
threshold: 1024,
algorithm: 'gzip',
deleteOriginFile: true
})
],
resolve: {
alias: {
'@': path.resolve('./src'), // 相对路径别名
},
},
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: '@import "./src/style/variable.scss";',
},
},
},
server: {
proxy: {
[env.VITE_APP_BASE_API]: {
target: env.VITE_SERVE,
// 需要代理跨域
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
build: {
rollupOptions: {
output: {
// sourcemap: true,
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
manualChunks(id){
// id为文件的绝对路径
if(id.includes('node_modules')){
return id.toString().split('node_modules/')[1].split('/')[0].toString()
}
}
}
}
}
}
}