来一次酣畅淋漓的vite打包优化吧

程序员他爱做梦 2024-06-26 22:20:39
最近发现项目首次加载特别慢,原来是打包出来的文件太大的原因。项目技术栈:vue3 + vite + ts + ant design vue

既然这样,那就开始打包优化吧。打包分析,结果如下:

第一步,ant-design-vue由全量引入改为按需引入。 修改前:

import type { App } from 'vue';import { Button } from './Button';import { Input, Layout,Table,Pagination } from 'ant-design-vue';import Antd from 'ant-design-vue';import VXETable from 'vxe-table';import * as echarts from 'echarts'export function registerGlobComp(app: App) { app.use(Input).use(Button).use(Layout).use(Antd).use(Table).use(VXETable); app.config.globalProperties.$echarts = echarts;}

修改后import type { App } from 'vue';// import { Button } from './Button';import { Input,Button, Layout,Table,Pagination,Card,Popover,Tooltip,Textarea,message,Select,Radio,RadioButton,RadioGroup,RangePicker,Cascader,Row,Col,Form,FormItem,Modal,Divider,TypographyText,Switch,Space,DatePicker,Empty,Transfer,Upload,List,Tabs,TabPane,Tag,Tree,Spin,InputNumber,Popconfirm,Typography,Avatar } from 'ant-design-vue';import Antd from 'ant-design-vue';import VXETable from 'vxe-table';import * as echarts from 'echarts'export function registerGlobComp(app: App) { app.use(Input).use(Button).use(Layout).use(Pagination).use(Card).use(Popover).use(Table).use(Tooltip).use(Select).use(Radio) .use(Cascader).use(Row).use(Col).use(Form).use(Modal).use(Divider).use(Switch).use(Space).use(DatePicker).use(Empty).use(Transfer) .use(Upload).use(List).use(Tabs).use(Tag).use(Tree).use(Spin).use(InputNumber).use(Popconfirm).use(Typography).use(Avatar); app.config.globalProperties.$echarts = echarts;}

再次打包,结果如下:

可以看到最大的两个js文件大小都减小了一些。但是还是很大。 观察打包结构图,发现index.js文件中包含了echarts,那么把echarts单独打包,试一下。修改vite.config.ts

再次打包,结果如下:

可以看到echarts已经被单独分开了,index.js文件的大小降低到了541k,但是单独一个echarts怎么打包完这么大?差不多1M了。查阅资料得知,我目前的echarts是全量引入的,echarts也可以按需引入,只需要单独封装一下。

新建一个commonEcharts.ts文件。注意事项已备注。// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。import * as echarts from "echarts/core";/** 引入柱状图and折线图图表,图表后缀都为 Chart */import { BarChart, LineChart,GaugeChart } from "echarts/charts";// 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Componentimport { TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, LegendComponent, ToolboxComponent} from "echarts/components";// 标签自动布局,全局过渡动画等特性import { LabelLayout, UniversalTransition } from "echarts/features";// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步import { CanvasRenderer } from "echarts/renderers";// 注册必须的组件echarts.use([ TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, BarChart, LabelLayout, GaugeChart, UniversalTransition, CanvasRenderer, LineChart, LegendComponent, ToolboxComponent]);// 导出export default echarts;

在原来的全局注册处导入,进行如下替换// import * as echarts from 'echarts'import echarts from '@/utils/commonEcharts'

再次打包,查看结果:

可以看到echarts的包体积大小减少了40%。 那么接下来,antd文件还是太大,打包后的大小超过了1M,为了进行更详细的优化,换一种分包的写法。 在vite.config.ts中,做出如下修改:

let antdSplitArr = [ 'node_modules/ant-design-vue/es/table', 'node_modules/ant-design-vue/es/select', 'node_modules/ant-design-vue/es/form', 'node_modules/ant-design-vue/es/menu', 'node_modules/ant-design-vue/es/vc-picker', 'node_modules/ant-design-vue/es/_util', 'node_modules/ant-design-vue/es/vc-table', 'node_modules/ant-design-vue/es/vc-select',]

在build中,使用包id匹配的方式,进行详细分包build:{ rollupOptions:{ output:{ manualChunks(id){ for(let i = 0; i < antdSplitArr.length; i++){ if(id.includes(antdSplitArr[i])){ return 'antd-split' } } if(id.includes('node_modules/echarts')){ return 'echarts' }else if(id.includes('node_modules/ant-design-vue/es/')){ return 'antd' }else if(id.includes('node_modules/vue') || id.includes('node_modules/pinia') || id.includes('node_modules/vue-router')){ return 'vue' }else if(id.includes('node_modules/@ant-design/icons-vue') || id.includes('node_modules/lodash') || id.includes('node_modules/sortable')){ return 'antd-icon-ld-sortable' } } } } },

最后再看一下打包结果吧:

已经没有大文件了,是不是很神奇。

2024-05-20更新。很多读者表示这篇文章帮到了他们,向我表示感谢。我也在此诚挚感谢大家的肯定。同时有读者反映,自己的项目在进行最后一个环节的id分包后,发布到线上出现了打不开的情况,报错如下:

在初始化某个变量前使用它导致报错初步分析是因为ant-design-vue的组件中引用了一些vue相关的特性,这些特性本来打包在ant-design-vue中的,但是经过id(也就是路径)分包后,检测到id.includes('node_modules/vue')时,自动拆离到了vue全家桶的包,导致了引用异常,可见这种方式的分包还是可能会有问题,而vite的开发时使用的esbuild,打包使用的rollup,我们配置的rollupOptions只在打包时生效。所以在开发环境不会报错。这个问题我已经关注到,希望读者在使用id分包的时候注意,如果有相同的问题,先不要采用id分包方式。

建议在vite.config.ts中使用如下方式分包(根据项目的依赖灵活配置):

manualChunks: { vue: ['vue', 'pinia', 'vue-router'], antd: ['ant-design-vue', '@ant-design/icons-vue'], echarts: ['echarts'],},

关于精细分包的新方法,我正在尝试,后续有时间我会更新完善。

作者:小刀飘逸链接:https://juejin.cn/post/7369776228168105994

0 阅读:0

程序员他爱做梦

简介:感谢大家的关注