前言
哈喽大家好!我是 嘟老板,在外漂泊多年,终是打算回老家找个工作安定下来,最近在各种做面试准备,顺便整理一波分享分享,希望能对大家有所帮助。今天要聊的主题是 首屏性能优化。
阅读本文您将收获:
- 首屏性能相关指标及统计方式介绍。
- 造成首屏加载缓慢的核心因素。
- 具体的优化措施。
- 等等...
性能指标
介绍
如何衡量首屏性能是否需要优化,不能单凭个人感觉下定论,用数据说话是最好的方式,性能指标 就是以数据的方式,为我们直观的展示首屏加载情况。
核心性能指标如下:
- FP(First Paint):首次渲染,在白屏结束时触发,当浏览器开始绘制内容,无论是什么内容,这个时间点就是 FP。
- FCP(First Contentful Paint):首次内容绘制,浏览器首次绘制来自 DOM 的内容,包括但不限于文本,图片,SVG,canvas等。
- FMP(First Meaningful Paint):首次渲染有意义的内容,没有固定的计算方法,不同公司的算法也可能不同。
- LCP(Largest Contentful Paint):最大内容绘制,没有固定的计算方法,不同公司的算法也可能不同。
- (了解)TBT(Total Blocking Time):总阻塞时间。
- (了解)TTI(Time To Interact):可交互时间。
放一张网图,帮助大家理解下各个指标所处的阶段:
在 FP 和 FCP 的解释中,涉及到两个名词:白屏和首屏,那什么是白屏和首屏呢?
白屏时间 = 地址栏输入网址后回车 - 浏览器出现第一个元素
首屏时间 = 地址栏输入网址后回车 - 浏览器第一屏渲染完成
统计
- FP/FCP:通过浏览器提供的 Performance API 计算。
打开浏览器控制台,输入 performance.getEntriesByType('paint')
回车执行,可以发现打印了一个数组结构:
其中,name 为 first-paint,即 FP,对应的 startTime 即 FP 消耗的时间;name 为 first-contentful-paint,即 FCP,对应的 startTime 即 FCP 消耗的时间。
- FMP/LCP:没有标准的统计算法,通常可借助 MutationObserver 手动实现。
影响性能的主要因素
影响首屏加载性能的因素主要分为以下两种:
- 网络延迟
- 资源太大
具体改进措施
针对网络延迟
针对网络延迟的优化,主要是一系列预处理操作,如 dns-prefetch,preconnect,prefetch,prerender,preload 等。
挑几个说说:
-
cdn,请求接近节点。
-
预加载 preload,在不执行资源的前提下,预先获取资源。
为需要预加载的资源标签添加值为 preload 的 rel 属性,如:
<link rel="preload" href="style.css" as="style" />
-
预渲染 prerender,让浏览器在后台进程渲染特定页面。
-
资源标签的 rel 属性支持 prerender 值,但是目前已经废弃,且不建议使用。
-
使用 prerender 工具,借助无头浏览器 puppeteer 预渲染指定页面,并通过服务端返回。
-
针对资源太大
针对资源太大的优化,核心是找到资源尺寸和请求数的平衡,合理借助缓存加速资源获取。当然了,终极方式必然是 SSR,然而不是所有项目都能推翻,用 SSR 重构的。
介绍几种常用方式:
-
分包 小即是快,将一个大的编译文件分成多个小的文件资源,提升获取速度。若使用 ebpack 构建,可使用 SplitChunksPlugin 插件;若使用 Vite 构建,可在
rollupOptions
下配置分块。 -
按需加载 仅在需要时加载对应的组员,如 Vue Router 路由配置的 component 设为
() => import(@/views/**/*.vue)
,实现路由懒加载。 -
缓存 资源缓存是十分有效且高效的优化方式,避免重复请求服务资源,直接在本地内存缓存或硬盘中获取。
缓存大致分为以下几类:
- 强缓存
-
(建议)Cache-Control 可设为以下值:
- (常用)max-age:表示强缓存的最大时间,单位 秒(s),如 max-age=300,表示请求正确返回时间的5分钟内再次加载,会命中强缓存。
- no-cache:不使用本地缓存,可使用协商缓存。
- no-store:直接禁止浏览器缓存数据,不能使用任何缓存。
- public:可被所有用户缓存,包括终端用户和 CDN 等中间代理服务器。
- private:只能被终端用户浏览器缓存,不允许 CDN 等中间代理服务器对其缓存。
-
Expires:响应头(response header)设置的过期时间,浏览器再次加载资源时,若仍在过期时间内,会命中强缓存。
-
- 协商缓存
-
Last-Modify/If-Modify-Since
浏览器首次请求某个资源时,服务器返回的响应头中会加上 Last-Modify,标识该资源的最后修改时间;当浏览器再次请求该资源时,请求头中会加上 If-Modify-Since,值为之前服务端返回的 Last-Modify。服务器收到请求后发现有 If-Modify-Since,根据资源的最后修改时间判断是否命中缓存。
-
(建议)Etag/If-None-Match 浏览器首次请求某个资源时,服务器响应头中会加上 Etag,值为当前资源在服务器的唯一标识。浏览器再次请求该资源时,请求头会加上 If-None-Match,值为之前服务端返回的 Etag。服务器收到请求后发现有 If-None-Match,则与被请求资源的相应校验串进行比对,判断是否命中协商缓存;
-
- 策略缓存,借助 ServiceWorker 实现。
- 强缓存
-
优化图片:推荐 WebP 类型,对于需要用户上传图片的功能,如头像,显示上传大小。
-
延迟加载,或滚动加载,只渲染可视区域内的内容。
-
tree-shaking,主流构建工具已内置,无需手动处理,需要注意编码方式,仅使用 esm 时才能正常 tree-shaking。
-
字体压缩,font-spider 按需压缩。
-
服务端渲染 SSR。
-
局部 SSR,仅特定页面使用服务端渲染,如活动页。
-
PWA,离线缓存。
工具
汇总下文中提及的工具,没准有用。
结语
本文重点介绍了 首屏加载性能优化,包括性能衡量指标,造成性能问题的主要因素及具体的优化措施,旨在帮助同学们加深对于首屏加载优化方式方法的了解和实操思路。希望对您有所帮助!
如您对文章内容有任何疑问或想深入讨论,欢迎评论区留下您的问题和见解。
技术简而不凡,创新生生不息。我是 嘟老板,咱们下期再会。
往期干货
- 🔜想开发 vscode 插件却不知从何入手?超速入门,助力你弹射起步
- 💯What?维护新老项目频繁切换node版本太恼火?开发一个vscode插件自动切换版本,从此告别烦恼
- (⊙ˍ⊙)哦? ElementPlus 官网导航栏有点意思,来看看咋实现的
- 🧨🧨🧨你想要的 RBAC 权限管理实现全流程来啦!~~ 代码含量过多,请谨慎阅读 ~~
- 💡💡💡Vue3 用了这么久还没体验过 JSX/TSX?来封装个业务弹窗玩玩
- 👏👏👏厉害了 Vue Vine !Vue 组件还能这样写!!!
- 听说过 BEM 吗?聊聊如何落地 BEM 规范
- 搞定 TS 装饰器,让你写 Node 接口更轻松
- 一文带你了解多数企业系统都在用的 RBAC 权限管理策略