Vite 打包后首屏加载太慢,怎么优化?
我用 Vite + Vue3 开发了一个项目,本地开发时很快,但 build 之后首屏加载特别慢,Lighthouse 评分很低。我已经试过开启 brotli 压缩和分包,但效果不明显。
是不是我的组件没做懒加载?比如下面这个路由写法是不是有问题?
<script setup>
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/dashboard',
component: () => import('@/views/Dashboard.vue')
}
]
const router = createRouter({ history: createWebHistory(), routes })
</script>
() => import('@/views/Dashboard.vue')这个其实是对的,路由懒加载没问题。但首屏加载慢的原因多了去了,路由懒加载只是其中一环。让我帮你理一理:
先检查打包产物到底有多大
在你的项目根目录运行
npm run build,然后看dist文件夹里每个 chunk 的大小。你可以用npm run preview跑起来,然后用 Chrome DevTools 的 Network 面板看具体哪个文件慢。几个常见的坑和解决办法
1. 第三方库没分离出来
你的 vite.config.ts 大概需要这样配置:
这样做的原理是把不常变化的第三方库和业务代码分开,浏览器可以长期缓存 vendor chunk。
2. 首屏路由的 chunk 太大
如果你的 Dashboard.vue 本身依赖了很多其他模块,即使路由懒加载了,加载 Dashboard 的时候还是会下载一堆东西。可以这样优化:
3. 首屏 CSS 没内联
Vite 默认会把 CSS 抽成单独文件,首屏需要等 CSS 加载完才能渲染。可以改成内联:
4. 资源预加载
首屏路由加载完之后,可以预加载其他可能访问的路由。用 vite 的 plugin 可以实现:
5. 关键组件直接渲染
如果首屏不需要等待整个路由加载完,可以先渲染一个骨架屏或者 Loading:
快速定位问题的方法
在你的入口文件
main.ts开头加一行:然后看 Network 面板里,哪个请求耗时最长。如果是一个大 JS 文件,就检查打包配置;如果是很多小请求,就考虑合并。
还有一个容易忽略的点
检查一下
index.html里的资源引用顺序:Vite 默认生成的 index.html 这个顺序应该是对的,但如果你手改过可能出问题。
你先按我说的这几个点排查一下,特别是第一条的 vendor 分离,做完之后重新 build 看下产物大小变化。如果还有问题,把你的 vite.config.ts 和项目依赖贴出来,我帮你具体分析。
首屏慢通常是因为没做代码分割后的预加载,或者打包产物太大没处理好。
先看几个关键点:
第一个,Vite 默认分包但不会预加载,你可以在
vite.config.js里加个manualChunks或者用build.rollupOptions显式分包,比如这样改一下就行:第二个,首屏关键资源建议用
prefetch或preload,比如你在 HTML 里加个<link rel="prefetch" href="/assets/xxx.js">,或者在路由里用meta: { prefetch: true }配合插件自动加。第三个,检查打包产物大小,用
vite-bundle-visualizer插件跑一下,看看哪个依赖占了大头,比如lodash、echarts这类大包,换成lodash-es或按需引入。还有个常见坑:别在入口文件里直接
import大库,比如import _ from 'lodash',这种会整个打进去,改成import debounce from 'lodash/debounce'就行。最后,如果用了 CDN,记得开启 HTTP2 + gzip + brotli,nginx 里 brotli 要装模块,不是光配个
gzip on就完事。你先按这些排查一遍,Lighthouse 能提 20 分以上。