6

前端性能优化方案归纳

 2 years ago
source link: https://www.fly63.com/article/detial/11236
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

对于前端开发来说,性能优化老生常谈了。不管是日常工作中,还是涉及到晋级答辩,性能都是频繁被我们提及的一个话题。

性能优化不是一劳永逸的解决方案,项目在发展过程,代码不断地迭代和变更。我们在某个阶段优化过的代码,过段时间性能又会慢慢下降,这也是前端开发常把性能挂在嘴边的原因。

当页面加载时间过长、交互操作不流畅时,会给用户带来很糟糕的体验。越是使用时间越长的产品,用户对体验的要求越高,如果出现卡顿或是加载缓慢,最坏的情况下会导致用户的流失。

对于性能优化,其实解决方案也比较常见和通用了,但是基本上也只有指导思想,实施起来还得具体项目具体分析。

常见的性能优化方案

对于前端应用来说,网络耗时、页面加载耗时、脚本执行耗时、渲染耗时等耗时情况会影响用户的等待时长,而 CPU 占用、内存占用、本地缓存占用等则可能会导致页面卡顿甚至卡死。

因此,性能优化可以分别从 耗时和资源占用 两方面来解决,我个人也比较喜欢将其称为“时间”和“空间”两个维度。

时间角度优化:减少耗时

我们知道浏览器在页面加载过程中,会进行以下的步骤:

  • 网络请求相关(发起 HTTP 请求从服务端获取页面资源,包括 html/css/JS/图片资源等)
  • 浏览器解析 HTML 和渲染页面
  • 加载 Javascript 代码时会暂停页面渲染(包括解析到外部资源,会发起 HTTP 请求获取并加载)

在浏览器的首次加载和渲染完成之后,不代表用户就可以马上交互和操作。根据业务代码加载过程,页面还会分别进入页面开始渲染、渲染完成、用户可交互等阶段。除此之外,页面交互过程中,会根据业务逻辑进行逻辑运算、页面更新。

题外话:为什么我们常常说要理解原理呢?性能优化便是个很好的例子,如果你不知道这个过程具体发生了什么,就很难找到地方下手去进行优化。

根据这个过程,我们可以从四个方面进行耗时优化:

  1. 网络请求优化。
  2. 首屏加载优化。
  3. 渲染过程优化。
  4. 计算/逻辑运行提速。

在前端性能优化实践中,网络请求优化和首屏加载优化方案使用频率最高,因为不管项目规模如何、各个模块和逻辑是否复杂,这两个方向的耗时优化方案都是比较通用的。相比之下,对于页面内容较多、交互逻辑/运算逻辑复杂的项目,才需要针对性地进行渲染过程优化和计算/逻辑运行提速。

一起来看看~

1. 网络请求优化

网络请求优化的目标在于减少网络资源的请求和加载耗时,如果考虑 HTTP 请求过程,显然我们可以从几个角度来进行优化:

  1. 请求链路:DNS 查询、部署 CDN 节点、缓存等。
  2. 数据大小:代码大小、图片资源等。

对于请求链路,核心的方案常常包括使用缓存,比如 DNS 缓存、CDN 缓存、HTTP 缓存、后台缓存等等,前端的话还可以考虑使用 Service Worker、PWA 等技术。使用缓存并非万能药,很多使用由于缓存的存在,我们在功能更新修复的时候还需要考虑缓存的情况。除此之外,还可以考虑使用 HTTP/2、HTTP/3 等提升资源请求速度,以及对多个请求进行合并,减少通信次数;对请求进行域名拆分,提升并发请求数量。

数据大小则主要考对请求资源进行合理的拆分(CSS、Javascript 脚本、图片/音频/视频等)和压缩,减少请求资源的体积,比如使用 Tree-shaking、代码分割、移除用不上的依赖项等。

在请求资源返回后,浏览器会进行解析和加载,这个过程会影响页面的可见时间,通过对首屏加载的优化,可有效地提升用户体验。

2. 首屏加载优化

首屏加载优化核心点在于两部分:

  1. 将页面内容尽快地展示给用户,减少页面白屏时间。
  2. 将用户可操作的时间尽量提前,避免用户无法操作的卡顿体验。

减少白屏时间除了我们常说的首屏加载耗时优化,还可以考虑使用一些过渡的动画,让用户感知到页面正在顺利加载,从而避免用户对于白屏页面或是静止页面产生烦躁和困惑。除了技术侧的优化,很多时候产品策略的调整,给用户带来的体验优化效果不低于技术手段优化,因此我们也需要重视。

整体的优化思路包括:尽可能提前页面可见,以及将用户可交互的时间提前。一般来说,我们需要尽可能地降低首屏需要的代码量和执行耗时,可以通过以下方式进行:

  • 对页面的内容进行分片/分屏加载
  • 仅加载需要的资源,通过异步或是懒加载的方式加载剩余资源
  • 使用骨架屏进行预渲染
  • 使用差异化服务,比如读写分离,对于不同场景按需加载所需要的模块
  • 使用服务端直出渲染,减少页面二次请求和渲染的耗时

有些时候,我们的页面也需要在客户端进行展示,此时可充分利用客户端的优势:

  • 配合客户端进行资源预请求和预加载,比如使用预热 Web 容器
  • 配合客户端将资源和数据进行离线,可用于下一次页面的快速渲染
  • 使用秒看技术,通过生成预览图片的方式提前将页面内容提供给用户

除了首屏渲染以外,用户在浏览器页面过程中,也会触发页面的二次运算和渲染,此时需要进行渲染过程的优化。

3. 渲染过程优化

渲染过程的优化要怎么定义呢?我们可以将其理解为首屏加载完成后,用户的操作交互触发的二次渲染。

主要思路是减少用户的操作等待时间,以及通过将页面渲染帧率保持在 60FPS 左右,提升页面交互和渲染的流畅度。包括但不限于以下方案:

  • 使用资源预加载,提升空闲时间的资源利用率
  • 减少/合并 dom 操作,减少浏览器渲染过程中的计算耗时
  • 使用离屏渲染,在页面不可见的地方提前进行渲染(比如 Canvas 离屏渲染)
  • 通过合理使用浏览器 GPU 能力,提升浏览器渲染效率(比如使用 css transform 代替 Canvas 缩放绘制)

以上这些,是对常见的 Web 页面渲染优化方案。对于运算逻辑复杂、计算量较大的业务逻辑,我们还需要进行计算/逻辑运行的提速。

4. 计算/逻辑运行提速

计算/逻辑运行速度优化的主要思路是“拆大为小、多路并行”,方式包括但不限于:

  • 通过将 Javscript 大任务进行拆解,结合异步任务的管理,避免出现长时间计算导致页面卡顿的情况
  • 将耗时长且非关键逻辑的计算拆离,比如使用 Web Worker
  • 通过使用运行效率更高的方式,减少计算耗时,比如使用 Webassembly
  • 通过将计算过程提前,减少计算等待时长,比如使用 AOT 技术
  • 通过使用更优的算法或是存储结构,提升计算效率,比如 VSCode 使用红黑树优化文本缓冲区的计算
  • 通过将计算结果缓存的方式,减少运算次数

以上便是 时间 维度的性能优化思路,还有 空间 维度的资源优化情况。

空间角度优化:降低资源占用

提到性能优化,大多数我们都在针对页面加载耗时进行优化,对资源占用的优化会更少,因为资源占用常常会直接受到用户设备性能和适应场景的影响,大多数情况下优化效果会比耗时优化局限,因此这里也只能说一些大概的思路。

资源占用常见的优化方式包括:

  • 合理使用缓存,不滥用用户的缓存资源(比如浏览器缓存、IndexDB),及时进行缓存清理
  • 避免存在内存泄露,比如尽量避免全局变量的使用、及时解除引用等
  • 避免复杂/异常的递归调用,导致调用栈的溢出
  • 通过使用数据结构享元的方式,减少对象的创建,从而减少内存占用

说到底,我们在做性能优化的时候,其实很多情况下会依赖时间换空间、空间换时间等方式。性能优化没有银弹,只能根据自己项目的实际情况做出取舍,选择相对合适的一种方案去进行优化。

对于页面耗时和资源占用的性能优化分析,大部分情况都可以使用 Chrome 开发者工具进行针对性的分析和优化。

原文 https://godbasin.github.io/2022/03/06/front-end-performance-optimization/

链接: https://www.fly63.com/article/detial/11236


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK