文章目录
  1. 1. 首屏渲染
    1. 1.1. 首屏内容加载
    2. 1.2. 首屏内容渲染
  2. 2. 页面更新
    1. 2.1. 用户操作
      1. 2.1.1. 事件委托
    2. 2.2. 页面渲染
      1. 2.2.1. DOM 操作合并
      2. 2.2.2. 页面滚动渲染
  3. 3. 结束语

对于内容复杂和变更频繁的前端应用,页面渲染也常常是性能优化的核心场景。

前面我有给大家整体地讲过《前端性能优化–方案归纳篇》,其实里面已经囊括了大多数场景下的一些性能优化的方向。关于加载流程相关的优化,也有在《前端性能优化–加载流程篇》一文中进行详细的介绍。

本文主要围绕页面渲染相关的内容,来进行性能优化分析。

首屏渲染

说到页面渲染,首屏的渲染显然是最首要的。其实前面在归纳篇也有介绍,首屏加载优化核心点在于:将页面内容尽快展示给用户,减少页面白屏时间。

首屏渲染包括了首屏内容的加载和渲染两个过程。

首屏内容加载

对于首屏加载过程,我们可以通过以下方式进行优化:

  • 使用骨架屏进行预渲染
  • 对页面进行分片/分屏加载,将页面可见/可交互时间提前
  • 优化资源加载的顺序和粒度,仅加载需要的资源,通过异步加载方式加载剩余资源
  • 使用差异化服务,比如读写分离,对于不同场景按需加载所需要的模块
  • 使用服务端直出渲染,减少页面二次请求和渲染的耗时
  • 使用秒看技术,通过预览的方式(比如图片)提前将页面内容提供给用户
  • 配合客户端进行资源预请求和预加载,比如使用预热 Web 容器
  • 配合客户端将资源和数据进行离线,可用于下一次页面的快速渲染

这里提到了很多的方向,但是否每个优化点都适用于自身的项目中,需要结合项目本身做调研和验证。举个简单的例子,最后两条优化点明显是基于有自研客户端的前提下,需要配合客户端一起做优化才可以实现。

实际上,对于首屏内容的优化,前端开发在项目中更常用的点是骨架屏、数据分片/分屏加载、SSR DOM 直出渲染这几种,因为这几个优化点相对来说方向明确、效果明确、实现相对简单。如果是想要对项目做差异化服务、做资源的拆分和优化,则可能随着项目的复杂度增加,方案难度提升、实现成本也增长。

首屏内容渲染

对于首屏内容渲染的过程,更多时候我们是指浏览器渲染 HTML 的过程。该过程可以优化的点也是我们常常提及的,浏览器渲染页面的优化过程,比如:

  • 将 CSS 放在<head>里,可用来避免浏览器渲染的重复计算
  • 将 JavaScript 脚本放在<body>的最后面,避免资源阻塞页面渲染
  • 减少 DOM 数量,减少浏览器渲染过程中的计算耗时
  • 通过合理使用浏览器 GPU 合成,提升浏览器渲染效率

以上这些,是我们在做首屏渲染时考虑渲染过程的优化点。虽然这些优化点属于前端基础和共识,也常常会出现在基础面试中。

很多时候我们为了准备面试而学习了很多的知识和原理,却容易在将知识和实践结合的过程中忘记。越是基础和简单的点,反而往往会在实际写代码的时候被忽略,直到性能出现了问题,这些基础的优化点才会被注意到。

当然,首屏性能的提升,除了渲染相关的,也还有上一篇我们提到的加载流程相关的优化

页面更新

除了首屏内容需要尽快加载和渲染以外,当页面内容需要更新的时候,我们也需要尽可能地减少更新内容渲染的耗时。

一般来说,页面更新场景我们常常会关注用户操作和页面渲染。

用户操作

页面内容的更新,一般有两种情况:

  1. 用户自身操作(点击、输入、拖拽等)的页面响应。
  2. 实时内容的变更(比如聊天室的消息提醒、弹幕等等)。

如果是用户自身的操作,则我们需要及时地更新页面内容,让用户感受到操作生效了。该过程应该是优先级最高的,一般需要同步进行。因为如果有别的任务在执行而导致主线程阻塞,就容易造成页面卡顿的体验。关于卡顿相关的,我会另外再起一篇文章介绍,这里就不过多展开啦。

至于实时内容的变更,优先级更多会比用户操作稍微低一些,也基本上都是异步进行的。我们还可以考虑对变更内容做合并、批量更新,也可以考虑定时拉取最新内容更新的方式。

事件委托

对于用户交互频繁的场景,我们还得注意事件的绑定。相信很多人都了解过事件委托,如果在列表数量内容较大的时候,对成千上万节点进行事件监听,也是不小的性能消耗。使用事件委托的方式,通过将事件绑定在父元素上,我们可以大量减少浏览器对元素的监听,也是在前端性能优化中比较简单和基础的一个做法。

事件委托是很常见的优化方式,需要注意的是,如果我们直接在document.body上进行事件委托,可能会带来额外的问题。由于浏览器在进行页面渲染的时候会有合成的步骤,合成的过程会先将页面分成不同的合成层,而用户与浏览器进行交互的时候需要接收事件。

如果我们在document.body上被绑定了事件,这时候整个页面都会被标记。即使我们的页面不关心某些部分的用户交互,合成器线程也必须与主线程进行通信,并在每次事件发生时进行等待。此时可以使用passive: true选项来解决。

页面渲染

我们在页面内容更新的时候,一般也可以考虑以下优化点:

  • 减少/合并 DOM 操作,减少页面更新的内容范围,减少浏览器渲染过程中的计算耗时
  • 对于页面动画,可以使用 CSS transition 能力,减少 DOM 属性的修改
  • 使用资源预加载,在空闲时间,提前将用户可能需要用到的资源进行获取并加载(比如下一页的内容)

DOM 操作合并

说到 DOM 操作的合并和减少,目前大多数前端框架都提供了虚拟 DOM 的能力(比如 Vue 和 React)。虚拟 DOM 本身就有对 DOM 操作和更新做优化,通过使用 JavaScript 对象模拟 DOM 元素,并在页面需要更新时对更新的部分做 DOM Diff,尽可能地减少内容的更新频率和范围。

虽然现在大多数前端项目都离不开前端框架,也正因为这些框架本身已经做了很多的优化,所以我们常常会忘记和忽略掉这些注意事项。

但也从侧面论证了,即使是很基础的优化点也需要重视,即使是简单的优化点也可以做出很棒的设计。

页面滚动渲染

考虑到页面滚动的场景,可能会出现性能问题的地方常常是长列表/页面的渲染。

由于页面内容过多,页面的 DOM 元素数量也很多,容易造成页面渲染的卡顿。在这样的情况下,我们可以考虑仅渲染可见区域的部分,比如页面内容超出滚动范围之外,就可以进行销毁,将页面的 DOM 数量保持在一定范围内。

结束语

本文主要围绕页面渲染和更新的过程,介绍了一些性能优化的方向。其实如果你有注意到,就会发现本文的内容大多数还是基础和简单的前端知识点。

还是那句话,前端基础和原理知识基本上大多数开发都掌握了,但是要怎么将这些知识在项目中发挥到最佳的作用呢?这才是我们工作中在不断探索和学习,获得经验和成长的关键点。

纸上得来终觉浅,了解一些知识很简单,但是要深入理解、熟练掌握后,再结合自身经验将它发挥出来,才是其价值的完整体现。

码生艰难,写文不易,给我家猪囤点猫粮了喵~

B站: 被删

查看Github有更多内容噢:https://github.com/godbasin
更欢迎来被删的前端游乐场边撸猫边学前端噢

如果你想要关注日常生活中的我,欢迎关注“牧羊的猪”公众号噢

作者:被删

出处:https://godbasin.github.io

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

文章目录
  1. 1. 首屏渲染
    1. 1.1. 首屏内容加载
    2. 1.2. 首屏内容渲染
  2. 2. 页面更新
    1. 2.1. 用户操作
      1. 2.1.1. 事件委托
    2. 2.2. 页面渲染
      1. 2.2.1. DOM 操作合并
      2. 2.2.2. 页面滚动渲染
  3. 3. 结束语