RN页面秒开方案与实践(一)

**来源:**Notion **原发布时间:**发布日期: 2025-10-30; 创建时间: 2025-10-31 07:04:21.846Z; 最后编辑时间: 2025-10-31 07:15:54.277Z **标签:**搬运总结、FE

原文:https://almond-oxygen-ceb.notion.site/RN-29d8b1cc19aa80d3b211d13d96a9ff1d?pvs=25


🌌

搬运与补充自《蒋宏伟-58RN页面秒开方案与实践》—2021全球大前端技术大会小册子

(似乎是内部资料了,网上搜不到买不到)

image.png

目录

[table_of_contents]


性能优化的业务收益

做性能优化,耗时是降低了,但对业务来说有什么收益呢?

首屏时间访问流失率的关系,发现:

性能的页面再优化,实际收益比预期

性能的页面优化,实际收益比预期

这就是性能优化收益的分化。

于是作者设计了几个指标,来驱动业务进行性能优化。

  1. 流失率
  2. 首屏时间
  3. 秒开收益 —如果页面实现了秒开,流失率会降低多少

首屏时间的采集指标

一个页面的加载流程有5个阶段:

  1. 用户进入
  2. 首次内容绘制FCP
  3. 业务组件渲染完成 Biz Update
  4. 最大内容绘制 LCP
  5. 可视区加载完成

这其中,2~4都可以作为首屏指标。那怎么去比较呢?

| | | | | | | | | | | | | |

W3C标准:

整个行业公认的、统一的度量衡

  • 统一性与互操作性 (Consistency)
  • 一旦成为标准,所有浏览器(Chrome, Firefox, Safari,Edge)都会用完全相同的方法去实现和计算它
  • 这意味着你在 Chrome 上测到的 LCP 和在 Firefox 上测到的 LCP是可以公平对比的(苹果-苹果对比)。
  • 而像 FMPbiz_update这样的非标准指标,在不同工具里的计算方法五花八门,你无法进行横向对比(苹果-橘子对比)。
  • 稳定性与权威性 (Stability)
  • 标准是经过 W3C 成员(包括谷歌、苹果、微软、Mozilla等所有巨头)的专家们反复讨论、审查和验证过的,确保了它的准确性稳定性
  • 它不会像 FMP那样,因为“不好用”或“不准确”而被官方废弃(Deprecated)。公司可以放心地围绕它构建长期的性能监控体系。
  • 强大的生态系统 (Ecosystem)
  • 因为它是标准,所有的第三方工具都会跟进支持。
  • 谷歌 (Google):把它作为 Core Web Vitals(核心网页指标) 之一,直接影响你的网站 SEO排名。这是最直接的商业价值
  • 监控工具:DataDog, New Relic, Sentry等所有性能监控平台都会原生支持 LCP。
  • 开发工具:Lighthouse, Chrome DevTools都会把它放在最显眼的位置。

侵入/非侵入式采集

侵入式采集” (IntrusiveMonitoring),也常被称为“有侵入性的监控”,它指的是:

**采集性能指标的这个行为本身,就已经对页面的性能产生了(通常是负面的)显著影响。**

换句话说,用来测量的工具(监控脚本)自己太重、太慢,导致你测量的对象(你的网页)也变慢了。这就违背了性能优化的初衷。

为什么LCP/FCP可以由浏览器自动计算,别的不行?

这触及到了两者最根本的区别:

LCP 和 FCP衡量的是浏览器的『渲染过程』,这是浏览器自己的本职工作

biz_update 和“可视区加载完成”衡量的是**『业务逻辑』**,浏览器对此一无所知。

可以把浏览器想象成一个“厨师”,它在厨房(渲染引擎)里做菜(渲染页面)。

  • FCP (首次内容绘制):厨师(浏览器)自己当然知道自己是什么时候把第一片菜叶(第一个像素/logo)放到盘子(屏幕)上的。它只需要在那个时刻“抬手看一眼表”,这个时间就是FCP。
  • LCP (最大内容绘制):厨师(浏览器)在往盘子里放菜时,自己当然也知道哪一块是“最大的主菜”(最大的图片或文本块)。它只需要在把这块主菜放上盘子的那一刻“再看一眼表”,这个时间就是LCP。

这一切都是浏览器渲染引擎内部的本职工作。它在绘制每个元素时,完全清楚这个元素是什么、有多大、在什么位置。所以它可以自动地、非侵入地计算出这些指标。

  • **biz_update**** (业务指标)**
  • 你(开发者)告诉浏览器:“当我的商品价格显示出来时,才算完成”。
  • 浏览器很困惑:“我怎么知道哪一串数字是‘价格’?我只看到一堆<div><span>
  • 浏览器无法理解你的“业务逻辑”。它不知道哪个元素对你的业务是“最重要的”。
  • 因此,你必须在你的代码里(比如从API拿到价格并渲染后),手动告诉浏览器,这个“手动通知”的动作就是侵入式埋点(performance.mark('biz_update'))。
  • “可视区加载完成” (定义太模糊)
  • 你(开发者)说:“等所有东西都加载完再告诉我。”
  • 浏览器又会困惑:“什么是‘所有东西’?你背景里那个1x1的追踪像素算吗?你页脚那个不重要的图标字体算吗?你页面上的广告脚本算吗?如果有个轮播图每5秒加载一张新图,那算不算‘永远加载不完’?”
  • “加载完成”是一个非常模糊且不稳定的概念。正因为它太难定义,W3C才放弃了它,转而选择了 LCP作为一个更稳定、更具代表性的替代方案。LCP不追求“全部完成”,它只追求“主角登场”。

所以,最终选定为LCP。


RN中的FCP采集

但是,LCP是web的标准,RN中没有实现。该怎么去采集呢?

image.png

  1. Native线程,记录用户进入时的Start时间戳
  2. Native线程,将Start时间戳注入到JS Context中
  3. JS线程,监听页面中渲染元素的布局事件
  4. JS线程,在页面渲染过程中计算,不断更新LCP值
  5. JS线程,计算得到End时间戳,并上报最终的LCP

最终的LCP = startTime - endTime

难点是怎么收敛LCP,即如何判断可视区完全加载?采用的规则是,所有元素都加载完成,且底部的元素也加载完成时。

怎判定是否加载完成?

元素的调用周期,是先调用render,再调用layout。只调用了render的元素,是没有加载完成的元素;只有两者都调用完成了,才是加载完成。