2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 前端性能优化梳理

前端性能优化梳理

时间:2023-06-14 01:05:07

相关推荐

前端性能优化梳理

性能优化的本质

优化的目的是展示更快、交互响应快、页面无卡顿情况。做优化需要理解浏览器加载和渲染的本质,可以参考浏览器进程 和认识优化渲染性能的本质。

雅虎军规

包括7个类别35条军规:

减少DOM节点数量:当遍历查询500和5000个DOM节点,进行事件绑定时,会有所差别。 当一个页面DOM节点过多,应该考虑使用无限滚动方案来使视窗节点可控(视频列表使用滑动窗口)。减少cookie大小:cookie 传输会造成带宽浪费,影响响应时间。消除不必要的cookies; 静态资源不需要 cookie,可以采用其他的域名,不会主动带上 cookie。避免图片src为空:图片src为空时,不同浏览器会有不同的副作用,会重新发起一起请求。

性能指标

首先,与用户感知性能相关有以下类型:

页面加载时间:页面以多快的速度加载和渲染元素到页面上。加载后响应时间:页面加载和执行js代码后多久能响应用户交互。运行时响应:页面加载完成后,对用户的交互响应时间。视觉稳定性:页面元素是否会以用户不期望的方式移动,并干扰用户的交互。流畅度:过渡和动画是否以一致的帧率渲染,并从一种状态流畅地过渡到另一种状态。

Google和W3C性能工作组提供了几种性能指标有:

First contentful paint (FCP):测量页面开始加载到某一块内容显示在页面上的时间。Largest contentful paint (LCP):测量页面开始加载到最大文本块内容或图片显示在页面中的时间。First input delay (FID):测量用户首次与网站进行交互(例如点击一个链接、按钮、js自定义控件)到浏览器真正进行响应的时间。Time to Interactive (TTI):测量从页面加载到可视化呈现、页面初始化脚本已经加载,并且可以可靠地快速响应用户的时间。Total blocking time (TBT):测量从FCP到TTI之间的时间,这个时间内主线程被阻塞无法响应用户输入。Cumulative layout shift (CLS):测量从页面开始加载到状态变为隐藏过程中,发生不可预期的 layout shifts 的累积分数。

其他指标:

DOMContentLoaded Event(DCL):DOM 解析完成时间,不包括资源加载(图片,样式表,子框架);OnLoad Event(L):页面所有资源加载完成时间。

Google定义了3个最核心的指标——Core Web Vitals:

Largest Contentful Paint (LCP): 测量加载性能。为了能提供较好的用户体验,LCP指标建议页面首次加载要在2.5s内完成。First Input Delay (FID): 测量交互性能。为了提供较好用户体验,交互时间建议在100ms或以内。Cumulative Layout Shift (CLS): 测量视觉稳定性。为了提供较好用户体验,页面应该维持CLS在0.1或以内。

对应的,Google官方库web-vitals,可以在线上或本地测量这3个指标。

LCP可能被这四个因素影响:

服务端响应时间Javascript和CSS引起的渲染卡顿资源加载时间客户端渲染

FID可能被这四个因素影响:

减少第三方代码的影响减少Javascript的执行时间最小化主线程工作减小请求数量和请求文件大小

CLS 能被这三个因素影响:

图片或视屏元素有大小属性,或者给他们保留一个空间大小,设置width、height,或者使用unsized-media feature policy。不要在一个已存在的元素上面插入内容,除了相应用户输入。使用 animation 或 transition 而不是直接触发布局改变。

更多详细优化请参考web.dev

性能工具

Google开发的这些工具都支持Core Web Vitals的测量:web-vitals。

结合这些工具做性能优化:

首先可以使用 Lighthouse,在本地进行测量,根据报告给出的一些建议进行优化;发布之后,可以使用 PageSpeed Insights 去看下线上的性能情况;接着,可以使用 Chrome User Experience Report API 去捞取线上过去30天的数据;发现数据有异常,可以使用 DevTools 工具进行具体代码定位分析;使用 Search Console's Core Web Vitals report 查看网站功能整体情况;使用 Web Vitals 扩展方便的看页面核心指标情况;

做性能优化时,会通过各种埋点,来收集用户数据,进行性能分析,简单来说是事后监控。同样的,也应该考虑事前监控,否则,每次发布需求后,去线上看数据是否下降或异常,性能优化永远作为"追赶者/弥补者"的角色在查问题、做优化。那么如何做事前监控——建立流水线机制:

PageSpeed Insights API或Lighthouse CI:把 Lighthouse 或 PageSpeed Insights API 集成到 CI 流水线中,输出报告分析。

Playwright或Puppeteer:Puppeteer和Playwright底层都是基于 ChromeDevTools Protocol,使用 e2e 自动化测试工具集成到流水线模拟用户操作,得到Chrome Trace Files,也就是平常录制 Performance 后,点击左上角下载的文件。。

Chrome Trace Files:根据谷歌提出的规则分析Trace文件,可以得到每个函数执行的时间。如果函数执行时间超过了一个临界值,可以抛出异常。如果一个函数每次的执行时间都超过了临界值,那么就值得注意了。但是还有一点需要思考的是:函数执行的时间是否超过临界值固然重要,但更重要的是这是不是用户的输入响应函数,与用户体验是否有关。

输出报告。定义异常临界值。如果异常过多,考虑是否卡发布流程。

H5 页面性能极致优化实践

1 环境准备

代理使用:whistle

本地环境、测试环境模拟:nginx

数据上报:TAM,RUM

前端代码打包分析:webpack-bundle-analyzer

首先使用本地代码分析问题,然后本地模拟线上环境验证优化效果,最后再部署到测试环境进行验证。

2性能指标选择

1. 页面加载时间

FCPLCPDCLL

2. 加载后响应时间——FID;

3. 视觉稳定性——CLS

3 优化前现网性能分析

页面进度条在首屏展示后还在持续 loading,持续时间长达 10s 左右,比较影响了用户体验。而进度条的加载时长和 onload 时间密切相关,所以需要减少 onload 时长。结合实际情况,我们使用 ChromeDevTool 作为性能分析工具来观察页面性能情况。

3.1 Network 分析:观察网络资源加载耗时及顺序

通常进行网络分析需要禁用缓存、启用网络限速(4g/3g) 模拟移动端弱网情况下的加载情况,因为 wifi 网络可能会抹平性能差距。可以发现onload事件被大量媒体资源阻塞了。

网络限速(Fast 3g)条件下,DCL 时长达到 9s 多,L 时长更是到了 20s 以上:

DOM的解析受JS加载和执行的影响,找到最长请求路径文件的耗时,尽量对JS进行压缩、拆分处理(HTTP2下),能减少 DOMContentLoaded 时间。图片、视频、iFrame等资源,会阻塞 onload 事件的触发,需要优化资源的加载时机,尽快触发onload。

3.2Performace 分析:观察页面渲染表现及JS执行情况

使用 Performance 模拟移动端注意手机处理器能力比 PC 差,因此一般将 CPU 设置为 4x slowdown 或 6x slowdown 进行模拟。

观察 Web Vitals ( FP / FCP / LCP / Layout Shift ) 核心页面指标 和 Timings 时长,发现 LCP、DCL和 Onload Event 时间较长,且出现了多次 Layout Shift(需要在 chrome console 左侧 more tools 中Rendeing中开启 Layout Shift Regions,在结果中的Experience 行点击 Layout Shift ,下面的Summary 面板找到具体的偏移内容)。因此,需要使得LCP 尽量早触发,应该减少页面大块元素的渲染时间,还有就是需要查看优化页面上存在的 Main Long Tasks 长任务数量和时长,选择在开发环境进行录制,如此可以在 Main Timeline 能看到具体的代码执行文件和消耗时长。

3.3Lighthouse 分析:对网站进行整体评分,找出可优化项

使用 ChromeDevTool 内置 lighthouse 对页面进行跑分,发现分数比较低,TTI,SI,TBT,LCP 等不合格,CLS 达到了良好的标准。lighthouse 的评分内容是根据项目整体加载进行打分的,审查出的问题同样包含 Network、Performance 的内容,会提供一些优化建议(Oppotunities 和 Diagnostics 项),如图片大小、移除无用JS等。

4优化加载耗时

首先,根据是否参与首屏渲染将影响 DOM 解析的 JS 资源划分为:

关键 JS,采用拆分处理进行优化;非关键 JS,采用延迟异步加载进行优化。

4.1关键JS拆分处理

使用 webpack-bundle-analyzer 进行打包分析,发现关键JS 文件数量多,总体积大,最大文件比较大。

首先,对Splitchunks 进行正确配置:不能简单的依靠 miniChunks 规则(比如最大公共文件 base.js 的 miniChunks = 3,会导致引用超过3次的模块就被打入该 JS)对页面依赖模块进行抽离打包,要根据具体情况拆分公共依赖。根据业务具体的需求,提取不同页面和组件都有的共同依赖(比如utils/log/api)到 base.js中:

base: {name: 'base',priority: 50,minChunks: 1,reuseExistingChunk: true,},

而其他未指定的公共依赖,新增一个 common.js,将阈值调高到 20 或更高(当前页面数76),让公共依赖成为大多数页面的依赖,提高依赖缓存利用率,两个文件加起来相比优化前体积减少了 50%(80kb)

其次,对公共组件进行按需加载:分析发现,对于使用 require 来加载 svg 图片,会导致 webpack 将 require 文件夹内的内容一并打包,导致页面图标组件冗余,可以通过配置 babel 的依赖加载路径调整 Icon 的引入方式,通过 import { Fire,ToTop} from 'Icons' 进行按需引入。如此之后,相比优化前体积减少 60%(54kb)。

最后,对业务组件进行代码分割(code splitting):考虑对不在首屏的页面组件进行拆分再延迟加载,减少业务代码 JS 大小和执行时长,可以使用react-loadable、@loadable/component 等库实现,也可以使用React 官方提供的React.lazy。不过,对页面组件进行代码分割会导致某些组件会有渲染的延迟,使用时应该综合用户体验和性能再做决定。

因为有使用到TreeShaking优化:对于没用到的包/模块/方法等,treeShaking 检查时会进行删除。可以给引入的包/模块(不是用来做 polyfill 或 shim 之类) 标记为sideEffects: false,只要它没有被引用到,整个模块/包都会被完整的移除。

优化前后效果对比:

4.2非关键 JS 延迟异步加载

如果在弱网情况,非关键 JS可能会成为影响 DOM 解析的因素。

对于可能无效的缓存组件(需要特定的操作才会触发)这类的非关键 JS 资源,可以使用 Resource Hints,针对资源做 Prefetch 处理:检测浏览器是否支持 prefech,支持的情况下我们可以创建 Prefetch 链接,不支持就使用旧逻辑直接加载,这样能更大程度保证页面性能,为下一个页面提供提前加载的支持:

const getPrefetchSupported = () => {const link = document.createElement('link');const { relList } = link;if (!relList || !relList.supports) {return [false, link];}return [relList.supports('prefetch'), link];};const prefetch = (url) => {const [isPrefetchSupport, link] = getPrefetchSupported();if (isPrefetchSupport) {link.rel = 'prefetch';link.as = type;link.href = url;document.head.appendChild(link);} else if (type === 'script') {// load script}};

对于其他比如监控上报等非关键JS资源,可以选择延迟加载它,或者在其他 JavaScript 之后立即加载,或者直到需要时才加载。

4.3优化媒体资源(图片,视频)加载

对于图片,视频等媒体资源的优化参考:前端图片优化,要使其不阻塞 onload,因此需要进行懒加载处理,而且需要注意懒加载不能阻塞业务的正常展示,应该做好超时处理、重试等兜底措施

4.4 其他资源加载优化

iframe 异步加载:iframe 是会阻塞onload 的 触发的,可以将将 iframe 的时机放在 onload 之后,并使用setTimeout触发异步加载iframe,可避免iframe带来的loading影响

字体文件压缩:可能会包含很多设计指定渲染的字体,当字体文件比较大的时候,也会影响到页面的加载和渲染,可以使用 fontmin 将字体资源进行压缩生成精简版的字体文件,压缩后体积减少字体文件30%。

埋点上报优化:图片请求若耗时长就会阻塞页面 onload 事件的触发,解决方案有三种:1. 延迟合并上报;2. 使用 Beacon API ;3. 使用 post 上报。可以采用延迟合并上报的方案,更多可以参考数据上报方式梳理进行优化

5 优化页面渲染

5.1SSR 页面优化

通过日志打点、查看 Nginx Accesslog 日志、网关监控耗时,得出以下数据:

SSR 服务器程序耗时是 20ms左右网关NGW -> SSR 服务器耗时 60ms 左右反向代理网关Nginx集群 -> 网关 NGW 耗时 60ms 左右

发现页面TTFB时间过长的根本原因是:NGW 网关部署和 反向代理网关 Nginx 集群、SSR 服务器程序不在同一区域,导致网络时延的产生。解决方案是让 NGW网关、反向代理网关 Nignx 集群和 SSR 服务器服务机房部署在同一区域,即执行对网关 NGW 进行扩容和分布式服务开启就近访问。

优化前后对比:

5.2 优化页面渲染时间

虽然,CSS文件的加载不会阻塞页面解析但会阻塞页面渲染。如果 CSS 文件较大或弱网情况,会影响到页面渲染时间,影响用户体验。通过利用ChromeDevTool 的 More Tools 里的 Coverage 工具,录制页面渲染时 CSS 的使用率,发现首屏的 CSS 使用率只有 20%,因此考虑对页面首屏的关键CSS进行内联(利用 webpack 插件 critters 实现),与加载其余完整 CSS 文件进行分离,让首屏页面渲染不被 CSS 阻塞,这样当CSS 资源正在下载时,页面就已经能开始正常渲染显示了。

5.3 优化页面视觉稳定性(CLS)

尽量使得首屏页面内容相对固定, 页面元素出现无突兀感,避免图标缺失、背景图缺失、字体大小改变导致页面抖动或者出现非预期页面元素导致页面抖动,采用解决方案如下:

确定SSR页面元素出现位置,根据数据提前做好布局首屏页面的小图可以通过base64处理,页面解析的时候就会立即展示减少动态内容对页面布局的影响,使用脱离文档流的方式或定好宽高

6 小结

优化前后Lighthouse 跑分对比(提升1倍以上)

优化前后 LCP与 onload耗时

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。