优化前预览
目前无任何处理,打包文件大小约为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() } } } } } } }
复制