Vue3 项目为什么第一次打开很慢?一文搞懂 SPA 首屏加载原理
相信很多人在部署完 Vue3 项目后,都有过这样的疑问:
为什么本地开发访问很快,而部署到服务器后,第一次打开页面却要等几秒钟?
尤其是在一些后台管理系统或者博客项目中,第一次进入页面时,经常会看到浏览器一直转圈,而刷新页面之后,速度又明显快了很多。
很多人第一反应就是:
是不是服务器太差?
其实,大多数情况下并不是服务器的问题,而是 SPA(Single Page Application,单页应用) 的加载机制决定了这一切。
本文就带大家彻底搞懂,为什么 Vue3 项目第一次打开会慢,以及后续为什么又会变快。
一、什么是 SPA?
Vue、React 等现代前端框架,默认开发的都是 SPA(单页应用)。
所谓单页应用,可以简单理解为:
整个网站实际上只有一个 HTML 页面。
例如访问:
https://www.example.com
浏览器真正下载的 HTML 文件其实只有:
index.html
打开浏览器开发者工具(F12),你会发现:
<body>
<div id="app"></div>
</body>
页面中几乎没有真正的内容。
那我们看到的首页、文章页、关于我页面又是怎么来的?
答案就是:
JavaScript 动态渲染。
二、浏览器第一次访问到底发生了什么?
假设现在访问一个 Vue3 博客。
浏览器真正经历的是下面这几个步骤:
用户访问网站
│
▼
请求 index.html
│
▼
下载 CSS
│
▼
下载 JS
│
▼
执行 JavaScript
│
▼
Vue 创建应用
│
▼
请求接口数据
│
▼
渲染页面
也就是说:
第一次打开页面,并不是简单下载一个 HTML。
而是需要下载整个前端应用。
三、为什么第一次打开最慢?
原因其实很简单。
因为浏览器什么都没有。
例如项目打包之后:
dist
│
├── index.html
├── app.js
├── vendor.js
├── style.css
├── logo.png
└── ...
浏览器第一次访问:
浏览器
↓
什么缓存都没有
↓
所有资源全部下载
例如:
index.html
↓
app.js
↓
vendor.js
↓
style.css
↓
字体
↓
图片
这些资源全部下载完成之后,页面才能真正显示出来。
因此:
第一次访问永远是最慢的一次。
四、为什么第二次访问又快了?
很多同学会发现:
第一次:
3 秒
刷新一次:
300 ms
为什么?
因为浏览器有缓存。
第一次下载完成后:
app.js
↓
保存到浏览器缓存
第二次访问:
浏览器
↓
发现本地已经有
↓
直接读取缓存
于是:
不用重新下载 JS
不用重新下载 CSS
不用重新下载字体
真正需要重新请求的,一般只有接口数据。
所以页面切换会非常快。
五、为什么 SPA 页面切换几乎秒开?
传统网站:
首页
↓
请求服务器
↓
返回 HTML
↓
重新加载
进入文章:
文章详情
↓
请求服务器
↓
返回 HTML
↓
重新加载
每切换一次页面,都要重新下载 HTML。
而 Vue SPA 不一样。
例如:
首页
↓
点击文章
↓
Vue Router
↓
切换组件
↓
完成
整个过程:
服务器根本没有返回新的页面。
只是:
隐藏旧组件
↓
显示新组件
所以速度非常快。
真正请求服务器的只有:
接口数据
例如:
GET /article/100
而不是:
GET article.html
六、Network 面板能看到什么?
如果觉得网站慢,千万不要凭感觉判断。
浏览器已经给我们提供了非常好的分析工具。
打开:
F12
↓
Network
然后勾选:
Disable cache
这样浏览器就不会读取缓存。
重新刷新页面。
你会看到:
index.html
app.js
vendor.js
style.css
font
image
以及它们各自:
- 下载时间
- 文件大小
- 请求顺序
例如:
app.js
980 KB
↓
下载耗时
1.2 s
一眼就能知道:
到底是谁拖慢了页面。
七、哪些资源通常最大?
对于 Vue 项目来说:
通常最大的都是:
JavaScript
例如:
Element Plus
ECharts
highlight.js
Vue
自己的业务代码
如果这些全部打包到一个 JS 文件中:
app.js
4 MB
浏览器第一次访问,就必须下载:
4 MB
网络越慢,等待时间越长。
因此:
很多性能优化其实都是围绕:
如何减少 JavaScript 体积。
展开的。
八、是不是服务器越好就一定越快?
很多人第一反应就是:
我换一台 8 核 16G 的服务器是不是就好了?
其实不一定。
例如:
服务器:
8 核
16G
但是:
app.js
5 MB
用户仍然需要下载:
5 MB
服务器再快,也无法改变:
网络传输需要时间。
所以:
前端性能优化更多关注的是:
减少下载
减少请求
减少等待
而不是:
疯狂升级服务器
九、后面还能怎么优化?
理解了第一次加载为什么慢之后,我们就可以针对性优化。
例如:
减少打包体积:
Element Plus
按需导入
减少传输数据:
Gzip
减少服务器 CPU:
预压缩
分析是谁最大:
rollup-plugin-visualizer
减少服务器带宽:
CDN
这些优化,并不是随便使用。
而是:
针对首次加载过程中不同的瓶颈进行优化。
后面的几篇文章,我们会逐一介绍。
十、总结
Vue3、React 等现代前端框架,大多数都属于 SPA(单页应用)。
第一次访问时,浏览器需要下载整个前端应用,因此通常也是最慢的一次。
而后续访问能够明显加快,主要得益于浏览器缓存以及前端路由机制。
当发现项目加载较慢时,不要急着升级服务器,更不要盲目优化。
正确的思路应该是:
- 打开浏览器 Network 面板分析请求;
- 找出真正耗时的资源;
- 根据瓶颈选择合适的优化方案。
性能优化从来都不是"加配置",而是先定位问题,再针对性优化。
在下一篇文章中,我们将介绍 Nginx 开启 Gzip 压缩,看看为什么一个 900KB 的 JavaScript 文件,经过压缩后可以缩小到原来的三分之一左右,以及浏览器又是如何自动解压这些资源的。