从4.2秒到1.1秒
去年我们给苏州高新区一家做电商SaaS的公司做性能优化,他们的商家后台首屏加载要4.2秒。技术团队之前也做过一些优化——压缩了CSS、开了Gzip,但效果不明显。我们花了三周时间,把加载时间压到1.1秒。下面是实际用到的7个手段,不是理论清单,是跑通了的实战经验。
技巧1:路由级别的代码分割
他们的后台是Vue 3项目,打包后主chunk有1.8MB。很多人知道用动态import做组件懒加载,但忽略了路由级别分割。我们把每个路由组件改成动态导入,main chunk直接从1.8MB降到340KB。首屏只需要加载登录页和首页的代码,其他页面用户点到了再加载。
具体操作就是把import Home from '@/views/Home.vue'改成const Home = () => import('@/views/Home.vue')。Vue Router天然支持这种写法,改完打包工具自动帮你分割。
技巧2:图片用WebP +懒加载
电商后台图片多,商品图、Banner图、活动图,一个页面几十张。我们把PNG/JPG统一转成WebP格式,体积平均缩减了65%。然后用Intersection Observer做了懒加载,视口外的图片不加载。
有个细节容易忽略:占位图。别用空白div,用户会觉得页面没加载完。我们用了一张10x10的模糊缩略图做占位,加载完成后有渐显动画,体感上流畅很多。
技巧3:Tree Shaking别只靠打包工具
Vite和Webpack都支持Tree Shaking,但不是所有代码都能被自动摇掉。他们的项目里用了lodash,打包后光lodash就占了72KB。改成import debounce from 'lodash/debounce'这种按需引入后,降到4KB。同理,moment.js换成day.js后从67KB降到7KB。
别信网上说的「打包工具会自动优化」,自己去打包分析里看看,你会惊讶地发现很多没用的代码被打进去了。用rollup-plugin-visualizer生成个 treemap,一目了然。
技巧4:虚拟列表处理大数据表格
商家后台有个订单列表,一次加载500条数据,渲染直接卡3秒。改用虚拟列表后,不管多少条数据,DOM节点始终保持在可视区域内的20-30个,渲染时间稳定在50ms以内。Vue用vue-virtual-scroller,React用react-window,API都很简单。
技巧5:关键CSS内联
浏览器渲染前要等CSSOM构建完成,如果CSS文件太大或者网络慢,首屏就卡住。我们把首屏需要的关键CSS(大概14KB)直接内联到HTML的style标签里,剩下的CSS异步加载。这样浏览器拿到HTML就能立刻渲染首屏,不用等外部CSS下载完。
苏州这边的网络环境总体不错,但移动端在弱网下差距很明显。4G网络下,这个优化把首屏渲染时间从2.8秒降到了1.5秒。
技巧6:接口请求并行化
首页加载时要调5个接口——用户信息、店铺数据、订单统计、消息列表、活动配置。之前是串行调的,一个接一个,总共耗时1.8秒。改成Promise.all并行后,总耗时降到了最慢那个接口的时间,大约600毫秒。
有个前提:接口之间不能有依赖关系。如果有,就把无依赖的并行,有依赖的串行,别一刀切。
技巧7:预渲染静态页面
后台的帮助中心、协议页面这种纯静态内容,之前也是走SPA路由动态渲染,白屏时间400ms+。改用vite-plugin-ssg做预渲染后,这些页面直接输出HTML,打开即见内容,0白屏。
说白了,性能优化没有银弹。每个项目瓶颈不一样,先用Lighthouse跑一遍,看审计报告里哪项分数低就改哪项。但上面这7个技巧覆盖了80%的常见问题,照着做一遍,大概率能拿到不错的效果。