Vue3 还原一个企业级后台-12-性能优化

发布时间:2026/10/8 17:25:20

Vue3 还原一个企业级后台-12-性能优化 性能优化路由懒加载、组件按需引入原型也要快。前面三篇业务模块写完页面一多首屏直接飙到 3 秒、打包 1.8MB——虽然 Mock 数据让原型看起来像真的但加载速度暴露了它是原型。本文用 5 个优化把首屏压到 0.9 秒打包缩到 580KB。一、先看现状优化前的基线数据优化之前先跑一组基线否则你不知道优化到底有没有效果。pnpmbuildVite 的构建输出会直接告诉你包体大小dist/index.html 0.45 kB dist/assets/index-d25b7a3e.css 398.52 kB # 全是 Element Plus 的样式 dist/assets/index-c8e1ff01.js 1420.31 kB # 所有页面 组件 Element PlusChrome DevTools 的 Lighthouse 跑一遍指标优化前FCP首屏内容绘制3.2sLCP最大内容绘制4.1sTTI可交互时间3.8s总 JS 体积1.42 MB总 CSS 体积398 KBLighthouse 评分65记下这组数据——每做完一个优化就重新跑一次看数字变化。性能优化最忌讳凭感觉一定要量化。二、路由懒加载首屏体积砍掉 60%这是效果最明显的一步。问题很简单目前的router/index.js是这样写的// ❌ 同步 import所有页面组件在首页就被打包进来了importApiRegistryfrom/views/api-manage/ApiRegistry.vueimportApiDetailfrom/views/api-manage/ApiDetail.vueimportModelHubfrom/views/model-hub/ModelHub.vueimportModelDetailfrom/views/model-hub/ModelDetail.vueimportPublishListfrom/views/model-publish/PublishList.vueimportPublishDetailfrom/views/model-publish/PublishDetail.vueimportLoginfrom/views/Login.vueconstroutes[{path:/,redirect:/api-manage/registry},{path:/,component:MainLayout,children:[{path:api-manage/registry,component:ApiRegistry},{path:api-manage/detail/:id,component:ApiDetail},{path:model-hub,component:ModelHub},{path:model-hub/detail/:id,component:ModelDetail},{path:model-publish,component:PublishList},{path:model-publish/detail/:id,component:PublishDetail},]},{path:/login,component:Login}]用户在首页/api-manage/registry但浏览器已经把模型汇聚、模型发布、登录页的代码全部下载了——这些页面用户根本没访问。2.1 改成动态 import// ✅ 动态 importVite 自动拆包访问时才加载constroutes[{path:/,redirect:/api-manage/registry},{path:/,component:MainLayout,children:[{path:api-manage/registry,component:()import(/views/api-manage/ApiRegistry.vue)},{path:api-manage/detail/:id,component:()import(/views/api-manage/ApiDetail.vue)},{path:model-hub,component:()import(/views/model-hub/ModelHub.vue)},{path:model-hub/detail/:id,component:()import(/views/model-hub/ModelDetail.vue)},{path:model-publish,component:()import(/views/model-publish/PublishList.vue)},{path:model-publish/detail/:id,component:()import(/views/model-publish/PublishDetail.vue)}]},{path:/login,component:()import(/views/Login.vue)}]这一改Vite 会在构建时把每个import()调用单独拆成一个 chunk。首屏只加载MainLayoutApiRegistry其他页面的代码在用户点击时才按需加载。2.2 魔法注释给 chunk 取个好名字默认的 chunk 名是数字 hash如3a2f1c.js调试时完全看不出谁是谁。加上魔法注释component:()import(/* webpackChunkName: api-registry *//views/api-manage/ApiRegistry.vue)component:()import(/* webpackChunkName: model-hub *//views/model-hub/ModelHub.vue)component:()import(/* webpackChunkName: model-publish *//views/model-publish/PublishList.vue)构建输出变成dist/assets/api-registry-3a2f1c.js 42 KB dist/assets/model-hub-b7e8d4.js 38 KB dist/assets/model-publish-9f1a3c.js 29 KB dist/assets/api-detail-5d2b8e.js 24 KB dist/assets/index-c8e1ff01.js 386 KB ← 只剩首屏需要的代码首屏 JS 从 1.42 MB 降到约 386 KB砍掉 73%。2.3 优化效果优化项变化首屏 JS1.42 MB → 0.39 MBFCP3.2s → 1.8s三、Element Plus 按需引入再砍 200KB目前项目是全局引入Element Plus// main.js — 全局引入importElementPlusfromelement-plusimportelement-plus/dist/index.cssapp.use(ElementPlus)这意味着即使你只用了el-table和el-button浏览器也要下载整个 Element Plus 库~800KB gzip 后 ~200KB。再加上 CSS 里的全部组件样式398KB加在一起就是 600KB 的冗余。3.1 安装按需引入插件pnpmadd-Dunplugin-vue-components unplugin-auto-import这两个插件分工明确unplugin-vue-components自动按需引入 Element Plus 组件你写el-button它自动import { ElButton } from element-plusunplugin-auto-import自动按需引入 Composition API你写ref、computed它自动import { ref, computed } from vue3.2 配置 vite.config.js// vite.config.jsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueimportAutoImportfromunplugin-auto-import/viteimportComponentsfromunplugin-vue-components/viteimport{ElementPlusResolver}fromunplugin-vue-components/resolversimport{fileURLToPath,URL}fromnode:urlexportdefaultdefineConfig({plugins:[vue(),AutoImport({resolvers:[ElementPlusResolver()],imports:[vue,vue-router,pinia],// 自动引入 ref/reactive/computed/useRouter/useStore 等dts:src/auto-imports.d.ts// 生成类型声明文件}),Components({resolvers:[ElementPlusResolver()],dts:src/components.d.ts// 生成组件类型声明文件})],resolve:{alias:{:fileURLToPath(newURL(./src,import.meta.url))}}})3.3 修改 main.js// main.js — 去掉全局引入import{createApp}fromvueimportAppfrom./App.vueimportrouterfrom./routerimportpiniafrom./storeimport./mockimport./styles/index.scssconstappcreateApp(App)app.use(pinia)app.use(router)// ❌ 删掉这行app.use(ElementPlus)app.mount(#app)现在你可以在任何.vue文件里直接写el-table、el-button、el-dialog插件会自动处理引入不需要手动 import。3.4 图标也要按需引入Element Plus 的图标库element-plus/icons-vue有 200 个图标全局引入也会增加包体积。正确的做法是按需引入// ❌ 全局引入打包进所有图标import*asElementPlusIconsVuefromelement-plus/icons-vuefor(const[key,component]ofObject.entries(ElementPlusIconsVue)){app.component(key,component)}// ✅ 按需引入只用到的图标才会打包import{Plus,Search,Edit,Delete,ArrowLeft}fromelement-plus/icons-vue// 在组件中使用el-button:iconPlus新增/el-button3.5 注意主题覆写的适配之前我们在第 04 篇用 SCSS 变量覆写了 Element Plus 主题。按需引入后SCSS 变量仍然生效——因为unplugin-vue-components只是控制 JS 组件的引入不干预 CSS。主题覆写是在styles/element-override.scss中定义通过vite.config.js的css.preprocessorOptions注入全局不受按需引入影响。// vite.config.js — 主题覆写配置保持不变css:{preprocessorOptions:{scss:{additionalData:use /styles/element-override.scss as *;}}}3.6 优化效果优化项变化Element Plus JS全量 → 按需省 ~200KB gzipElement Plus CSS398KB → ~60KB只含用到的组件样式图标全量 200 → 按需 8 个四、路由切换优化加个进度条和缓存4.1 NProgress让加载有反馈路由懒加载后首次访问模型汇聚页面会有 300~500ms 的加载时间。这段时间用户盯着白屏体验很差。加个进度条pnpmaddnprogresspnpmadd-Dtypes/nprogress// router/index.jsimportNProgressfromnprogressimportnprogress/nprogress.cssNProgress.configure({showSpinner:false,speed:400,minimum:0.2})router.beforeEach((to,from,next){NProgress.start()next()})router.afterEach((){NProgress.done()})页面顶部的蓝色进度条一闪而过用户知道正在加载不会误以为卡死了。4.2 KeepAlive不让状态白费模型汇聚的详情页有 3 个 Tab用户在接口参数 Tab 里编辑了几行数据切到模型文件 Tab 看了一眼再切回来——编辑的内容没了。!-- MainLayout.vue -- template div classmain-layout TopBar / div classlayout-body SideNav / div classcontent-area router-view v-slot{ Component } keep-alive :includecachedViews component :isComponent / /keep-alive /router-view /div /div /div /template script setup import { ref } from vue // 只缓存需要保持状态的页面 const cachedViews ref([ ModelHub, // 模型汇聚列表搜索条件保持 ApiRegistry, // API 注册列表筛选状态保持 ModelDetail // 模型详情Tab 状态保持 ]) /scriptinclude数组按组件name匹配。未在数组中的页面不会缓存切走即销毁不占内存。五、构建优化进一步缩小包体积5.1 拆 vendor chunkElement Plus 的el-table、el-form、el-dialog这些组件在多个页面中复用。默认情况下它们可能被打进每个页面的 chunk 里导致重复打包。用manualChunks把它们单独拆出来// vite.config.jsexportdefaultdefineConfig({build:{rollupOptions:{output:{manualChunks:{element-plus:[element-plus],// Element Plus 单独打包vue-vendor:[vue,vue-router,pinia]// Vue 全家桶单独打包}}}}})这样 Element Plus 的代码只会被打包一次所有页面共享一个element-plus-xxx.jschunk。浏览器第二次访问时直接用缓存不需要重新下载。5.2 可视化分析看看到底谁占了大头拆完还不放心用rollup-plugin-visualizer生成一张可视化图pnpmadd-Drollup-plugin-visualizer// vite.config.jsimport{visualizer}fromrollup-plugin-visualizerexportdefaultdefineConfig({plugins:[// ... 其他插件visualizer({open:true,// 构建完自动打开浏览器gzipSize:true,// 显示 gzip 后大小brotliSize:true// 显示 brotli 后大小})]})构建后自动打开stats.html一张树状图直观展示每个模块的体积占比。一眼能看到Element Plus 的表格组件最胖~80KBElement Plus 图表库占了 60KB其实我们没用图表mockjs 占了 45KB……5.3 排除未使用的依赖可视化分析暴露的第一个问题mockjs被打进生产包了。第 11 篇我们已经用import.meta.env.DEV做了环境判断但为了确保 tree-shaking 彻底生效再加一道保险// vite.config.jsexportdefaultdefineConfig({define:{__MOCK_ENABLED__:false// 生产环境关闭 Mock}})同时确保 mock 目录只在开发环境 import生产构建时 Vite 会直接把这部分代码从产物中剔除。六、最终效果用数据说话所有优化完成后再跑一次pnpm build和 Lighthouse指标优化前优化后提升FCP3.2s0.9s-72%LCP4.1s1.2s-71%TTI3.8s1.1s-71%首屏 JS1.42 MB0.21 MB-85%总 CSS398 KB62 KB-84%构建产物1.82 MB0.58 MB-68%Lighthouse659227 分6.1 各优化项的贡献优化项体积缩减FCP 改善路由懒加载~1 MB-1.4sElement Plus 按需引入~340 KB-0.5s图标按需引入~80 KB-0.1svendor chunk 拆分无直接缩减但后续访问 0 下载—mock 生产剔除~45 KB-0.1sNProgress无体积变化改善心理等待—路由懒加载贡献了最大的改进——它直接把 6 个页面的代码从首屏中移除。Element Plus 按需引入的效果也很显著CSS 从 398KB 降到 62KB节省了 84%。七、性能优化的铁律三条原则做完这轮优化沉淀三条原则1. 先量再优。优化前跑 Lighthouse /pnpm build记基线优化后跑了对比。没有数据你永远不知道优化够了没。2. 改动最小的优化往往收益最大。路由懒加载只改了路由定义10 行代码首屏体积砍了 73%。Element Plus 按需引入也只加了两个插件配置。真正的性能杀手通常是架构层面的问题不是某个函数慢了 3ms。3. 不要过度优化。Vite 本身的 tree-shaking 和按需加载已经做得很好别一上来就手写terser配置、自定义分包策略。先用工具层的默认优化不够再补。本项目这 5 个优化做完Lighthouse 92 分对于一个原型项目来说已经远超预期。上一篇11 - Mock 数据策略让原型看起来真实下一篇预告代码写完、性能达标最后一件事——怎么证明你还原了 Figma下一篇用 Playwright pixelmatch 做自动化像素对比把 Figma 截图和开发截图放到一起量化像素一致度。
延伸阅读

更多相关文章

2026/10/6 18:06:07

AI Agent技能开发实战:从零构建智能体工具链与自动化应用

这次我们来看一个关于 Agent Skills 的实战教程资源。这个标题指向的是一套号称“最全最细”的 Agent Skills 实战教程,目标是帮助学习者快速入门并掌握相关技能。对于想进入 AI Agent 开发领域的人来说,最关心的不是概念有多复杂,而是有没有…

2026/10/6 18:07:48

基于Spring Boot与Milvus的RAG企业知识库实战搭建指南

在企业级应用开发中,如何让AI大模型精准地回答公司内部文档、产品手册、技术规范等私有知识,而不是“一本正经地胡说八道”,是许多开发者面临的共同挑战。传统的微调方案成本高昂、周期长,且难以应对知识的快速更新。此时&#xf…

2026/10/8 17:22:10

Ethernet-APL会取代4-20mA?石化现场仪表通信的演进与终局判断

站在老装置机柜间里,看着端子排上一圈圈泛黄的4-20mA信号线,我突然想起前阵子做Ethernet-APL现场测试时的对比画面。一边是石化现场用了三十年的模拟信号老伙计,一边是能塞进本质安全回路里的工业以太网新兵——这问题迟早要正面回答&#xf…

2026/10/8 17:22:10

工业互联网与DCS不是替代关系,而是系统性耦合

工业互联网和传统工控的关系,不是“新旧替代”的线性叙事,而是一场静默却深刻的系统性耦合——就像给一台精密运转三十年的汽轮机,不是拆掉它换上电动机,而是给它加装神经传感网络、嵌入实时诊断模块、打通上下游数据脉络&#xf…

2026/10/8 17:22:10

Context-Mode:LLM上下文管理的四种模式与工程实践

做 AI 应用这段时间,我最大的感受是:选模型只是第一步,真正决定产品体验的往往是你怎么管理上下文。尤其是做 agent 类、深度对话类应用时,用户聊着聊着,模型就开始“失忆”——要么忘记前面说过的关键信息&#xff0c…

2026/10/8 17:22:10

AI Skills工程化:Genkit+GKE生产级落地实践

1. 这不是“技能列表”,而是一套可落地的AI工程化能力体系 最近在多个技术社区和开发者群聊里,反复看到一个词被高频提起: skills 。它既不是简历上泛泛而谈的“熟练掌握Python”“熟悉React”,也不是HR系统里打勾的软技能标签&…

2026/10/8 17:22:10

Agent Skills实战指南:从npx安装到Agent集成

1. 从“skills”这个热词说起:它到底是什么,为什么突然火了最近一段时间,不管是在开发者社区、AI工具圈,还是各种技术交流群里,“skills”这个词出现的频率高得离谱。很多人第一次看到“skills”这个词,脑子…

2026/10/8 10:03:18

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/8 10:03:20

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:02:17

自然数立方等于连续奇数之和:从证明到编程验证

十几年来我一直游走在数学科普和编程教学这两块内容之间,对“看起来像魔法、拆开全是数学”的结论总是格外敏感。最近翻资料时又撞见一句话:任何一个自然数 m 的立方,都可以写成 m 个连续奇数之和。2 的立方等于 3 加 5,3 的立方等…

2026/10/8 0:02:17

C#上位机SSH连接实战:用SSH.NET补齐超时、批量与密钥认证

简介:这是一份基于 C# 开发的 SSH 连接功能半成品工程,原本作为另一个主项目的子功能模块,现独立打包分享。工程采用 WinForms 界面,包含源码、解决方案、安装部署工程、NuGet 依赖包及说明文档,适合正在做远程连接、网…

2026/10/8 0:02:17

Java SpringBoot一体化智能售后系统设计与实现全解析

毕业设计年年做,Java Web 方向的题目翻来覆去就那么几个,但“一体化智能售后系统”这个题,每次看到我都觉得值得认真聊一聊。它不是一个简单 curd 堆出来的管理系统,而是把客户、工单、派单、处理、回访、统计整条链路串起来的一套…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑