一、先明确性能指标
优化前先确定度量口径,常用指标:
- FP / FCP(首次绘制 / 首次内容绘制)—— 白屏优化的核心指标
- LCP(最大内容绘制)—— 首屏优化的核心指标
- TTI(可交互时间)、FID / INP(交互响应)
- CLS(布局偏移)
二、白屏优化方案
白屏的本质:HTML 加载后,JS 尚未执行完成、页面没有内容可渲染。
1. 减少白屏持续时间
- SSR / 预渲染
- 服务端渲染(Nuxt / Next / 自研 Node 中间层),首屏内容由服务端直出
- 对于内容固定的页面用
prerender-spa-plugin/vite-plugin-prerender预渲染成静态 HTML
- HTML 骨架 / Loading 动画
- 在 HTML 模板中内置骨架屏(Skeleton)或 Loading,JS 执行前用户就能看到占位内容,感知白屏时间大幅降低
- 可用
page-skeleton-webpack-plugin或手写骨架组件
- inline critical CSS:将首屏关键 CSS 内联到 HTML 中,避免 CSS 阻塞渲染
2. 加快 JS 执行
- 路由懒加载 + 组件懒加载:
(component: () => import(...)),避免首屏加载全量 JS - 代码分割(Code Splitting):按路由 / 按业务域拆 chunk
- DLL / 缓存长期不变的库(比如这个仓库里的
.temp/dll-development就是这种思路) - HTTP 缓存 + 长效强缓存:文件名带 hash,
Cache-Control: max-age=31536000, immutable - HTML 不缓存,JS/CSS 长缓存
- Tree Shaking:移除无用代码,避免引入组件库全量包(按需引入)
3. 网络层优化
- HTTP/2 或 HTTP/3:多路复用,消除队头阻塞
- CDN 加速:静态资源就近分发
- 域名收敛/分域:减少 DNS 查询,同时利用分域突破并发限制
- 资源压缩:Gzip / Brotli,图片 WebP / AVIF
- preload / prefetch / dns-prefetch:
<link rel="preload" as="script">提前加载首屏关键 JS<link rel="dns-prefetch">/preconnect提前建连
三、首屏优化方案
首屏优化的目标不只是"出现内容",而是"最大内容尽快出现且可交互"。
1. 资源维度
- 首屏资源最小化:首屏只加载必须的 JS/CSS,非首屏用
prefetch/ 动态 import - 图片优化:
- 懒加载(
loading="lazy"、IntersectionObserver) - 使用 WebP/AVIF、响应式图片(
srcset) - LCP 图片用
fetchpriority="high"+preload优先加载
- 懒加载(
- 字体优化:
font-display: swap,字体子集化,避免 FOIT
2. 数据维度
- 接口聚合:首屏多个接口合并为一个 BFF 聚合接口,减少串行请求
- 并行请求:串行改并行(
Promise.all) - 数据预取:SSR 时服务端直接取数据直出;CSR 可在 HTML 里 inline 首屏数据(
window.__INITIAL_STATE__) - 接口缓存:localStorage / 内存缓存上次数据,先渲染旧数据再静默更新
- 分页 / 虚拟滚动:长列表用虚拟列表(如
vue-virtual-scroller),首屏只渲染可视区域
3. 渲染维度
- v-if 延迟渲染非首屏组件、弹窗组件懒挂载
- 异步组件 + 骨架屏:
defineAsyncComponent配合 loading 组件 - 避免同步阻塞:大数据计算放 Web Worker;避免长任务(Task > 50ms)
- 减少重排重绘:批量 DOM 操作、
transform替代top/left
4. 缓存与分发
- PWA / Service Worker:静态资源离线缓存,二次访问秒开
- 客户端缓存 HTML:移动端 Hybrid 容器可以做离线包 / 直出快照
- 动静分离:静态资源上 CDN,动态请求走机房就近接入
四、Web 端(PC)专项
- 浏览器兼容下做Polyfill 按需加载(
@babel/preset-env+useBuiltIns: 'usage'),现代浏览器不加载 legacy chunk(module/nomodule) - 弱网降级:接口超时兜底、错误重试
- 监控体系:接入性能监控(如公司内 Raptor / 自建上报),采集 FCP/LCP/白屏率,用 RUM 数据驱动优化
- 构建产物分析:
webpack-bundle-analyzer/rollup-plugin-visualizer找大包,剔除重复依赖
五、移动端专项
移动端特点:弱网、低端机、内存受限,优化侧重不同。
网络层
- 弱网优化:请求合并、降低首屏请求优先级、HTTP/2 复用、QUIC/HTTP3 抗弱网
- 离线包:Hybrid / 小程序场景,静态资源提前下发本地缓存
- 图片按网络环境加载:弱网加载低清图 / 降级 WebP
渲染层
- 低端机降级:检测设备性能,关闭复杂动画、减少模糊/阴影效果
- GPU 加速:合理使用
transform/will-change,但避免层爆炸 - 长列表虚拟滚动:移动端尤其重要,避免大量 DOM 节点
- 减少 JS 执行时长:低端机 CPU 弱,避免启动时大量同步 JS,可把非核心逻辑延迟到
requestIdleCallback执行
容器层
- H5 秒开方案:客户端预加载 / 预初始化 WebView、URL 预热
- 原生骨架屏直出:Native 端先渲染骨架,H5 ready 后替换
- RN / 小程序:分包加载、按需注入,启动只加载核心 bundle
六、优化落地路径建议
- 先度量:接入性能监控,量化白屏率、FCP、LCP 基线
- 找瓶颈:用 Lighthouse / Chrome DevTools Performance 面板定位是网络慢、JS 大还是渲染阻塞
- 分优先级做:
- 高 ROI:路由懒加载、骨架屏、CDN+强缓存、图片懒加载
- 中 ROI:SSR/预渲染、接口聚合、BFF 直出
- 低 ROI / 高成本:Service Worker、离线包、Web Worker 重构
- 持续监控防劣化:性能指标纳入 CI 卡口和线上监控告警