减少 Vue 应用白屏时间的经验总结
作者:CAD老兵
Vue 项目日益庞大,首屏渲染变慢、页面打开时出现“白屏”的现象屡见不鲜,本文将系统讲解白屏的成因,并提供多种实用优化策略与示例代码,帮助你在实际项目中显著提升用户体验
随着前端应用不断发展,Vue 项目日益庞大,首屏渲染变慢、页面打开时出现“白屏”的现象屡见不鲜。本文将系统讲解白屏的成因,并提供多种 实用优化策略与示例代码,帮助你在实际项目中显著提升用户体验。
什么是白屏时间?
白屏时间是指用户从点击链接或输入地址到页面开始有内容显示之间的这段时间。其根本原因通常包括:
- JS/CSS 资源体积大,下载与解析耗时
- 应用初始化慢(Vue 挂载、hydrate)
- 网络慢或资源未缓存
- 图片、字体加载阻塞渲染
优化白屏的目标是:尽快渲染首屏关键内容,并让用户“感知”到页面在加载。
优化策略总览
| 优化策略 | 适用场景 | 难度 | 效果 |
|---|---|---|---|
| 预渲染 / SSR | 静态官网 / 内容站 | ⭐⭐ | 💥💥💥💥 |
| 路由懒加载 / 动态导入 | 多页面应用 | ⭐ | 💥💥💥 |
| 骨架屏 / 占位内容 | 产品页 / 营销页 | ⭐ | 💥💥💥 |
| 图片懒加载 / 字体优化 | 图片多 / 字体多页面 | ⭐ | 💥💥 |
| 延迟加载重型模块 | 图表、监控、动画 | ⭐ | 💥💥💥 |
| 资源压缩 / 缓存优化 | 所有页面 | ⭐ | 💥💥 |
| 内联关键 CSS / 预加载 | 内容精简、强调首屏性能的页面 | ⭐⭐ | 💥💥💥 |
一、使用预渲染(Prerender)或 SSR
原理说明:
- SSR 在服务器生成 HTML,可避免客户端加载过久才有内容。
- 对静态页面,使用构建时 预渲染(Prerender)更高效。
💡 示例:使用vite-plugin-prerender-spa实现预渲染
npm install vite-plugin-prerender-spa --save-dev
\`\`\`
\`\`\`ts
// vite.config.ts
import prerender from 'vite-plugin-prerender-spa'
export default {
plugins: [
prerender({
staticDir: 'dist',
routes: ['/', '/about'] // 构建时生成 HTML
})
]
}
二、代码拆分 + 路由懒加载
原理说明:
- 初始加载越轻,白屏越短。
- Vue 支持
import()实现 组件按需加载,并与路由结合使用。
示例:
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
const Home = () => import('@/views/Home.vue')
const About = () => import('@/views/About.vue')
export default createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
})
三、使用骨架屏代替白屏
原理说明:
骨架屏是应用加载中展示的占位元素,可用来传达“页面正在加载”而不是白屏状态。
示例:简单骨架屏组件
<template>
<div v-if="loading" class="skeleton"></div>
<HomePage v-else />
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import HomePage from './views/Home.vue'
const loading = ref(true)
onMounted(() => setTimeout(() => (loading.value = false), 1500))
</script>
<style>
.skeleton {
height: 100vh;
background: linear-gradient(90deg, #eee 25%, #ddd 50%, #eee 75%);
background-size: 200% 100%;
animation: shimmer 1.2s infinite;
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
</style>
四、图片懒加载与字体优化
原理说明:
- 图片和字体资源体积大,可能阻塞页面渲染。
- 图片应懒加载;字体应设置
font-display: swap。
示例:
<!-- 懒加载图片指令 -->
<img v-lazy="imgUrl" />
<script setup lang="ts">
import { onMounted } from 'vue'
const imgUrl = '/big-banner.jpg'
</script>
// main.ts
app.directive('lazy', {
mounted(el, binding) {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
el.src = binding.value
observer.disconnect()
}
})
observer.observe(el)
}
})
@font-face {
font-family: 'MyFont';
src: url('/fonts/my-font.woff2') format('woff2');
font-display: swap;
}
五、延迟加载非关键模块
原理说明:
不必首屏渲染的代码(如 ECharts、监控 SDK、动画库)应延迟加载,避免阻塞。
示例:
onMounted(() => {
requestIdleCallback(() => {
import('echarts').then(echarts => {
const chart = echarts.init(document.getElementById('chart')!)
chart.setOption({ title: { text: '懒加载图表' } })
})
})
})
六、使用内联关键 CSS
原理说明:
- 首屏渲染常依赖一些关键样式(比如布局、导航栏)。
- 可通过 Vite 插件将其提取并 内联 到 HTML 中。
示例:
npm install vite-plugin-critical --save-dev
// vite.config.ts
import critical from 'vite-plugin-critical'
export default {
plugins: [
critical({
criticalUrl: '',
criticalBase: './dist/',
criticalPages: [{ uri: '', template: 'index' }]
})
]
}
七、开启 Gzip/Brotli 压缩
原理说明:
资源压缩后体积显著减少,浏览器解压速度远快于传输速度,提升加载性能。
示例:
npm install vite-plugin-compression --save-dev
// vite.config.ts
import compression from 'vite-plugin-compression'
export default {
plugins: [compression({ algorithm: 'gzip' })]
}
八、使用 preload 加快关键资源加载
原理说明:
使用 <link rel="preload"> 或 <link rel="modulepreload"> 告诉浏览器:这资源是关键路径,先加载它!
示例:
<!-- index.html --> <link rel="preload" href="/fonts/my-font.woff2" rel="external nofollow" as="font" type="font/woff2" crossorigin /> <link rel="modulepreload" href="/assets/main.js" rel="external nofollow" />
九、总结建议:实用组合方案
| 项目类型 | 推荐组合策略 |
|---|---|
| 内容静态网站 | 预渲染 + 骨架屏 + 图片懒加载 |
| 后台管理系统 | 路由懒加载 + 模块延迟 + Gzip + 缓存优化 |
| H5 页面 / 小程序壳 | 内联 CSS + 字体优化 + 骨架屏 + preload |
| 企业官网 / 产品页 | 预渲染 + 骨架屏 + 关键 CSS 提取 + preload + 动效延迟加载 |
到此这篇关于减少 Vue 应用白屏时间的经验总结的文章就介绍到这了,更多相关减少Vue白屏时间内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
