只读属性本身不能测量实例化耗时,需在初始化逻辑中嵌入时间戳并写入只读字段(如_initDurationMs),再通过审计服务聚合分析;其本质是可信状态快照,不参与执行过程,但可作为耗时审计的最终锚点。

直接利用只读属性本身无法测量实例化耗时——它只限制修改,不提供计时能力。真正可行的路径是:在组件初始化逻辑中嵌入轻量级时间戳采集,并将结果写入只读字段(如自定义元数据或日志属性),再通过统一审计服务批量读取、聚合分析。
明确只读属性的定位与边界
只读属性(如 Project 中的“计划工期”“受保护的实际加班工时”,或阅读器 SDK 中的 nodeType、dataId)本质是状态快照或计算结果的最终呈现,不可写入但可安全读取。它不参与执行过程,也不触发钩子。因此:
- 不能靠监听只读字段变化来捕获实例化时刻
- 不能在只读字段上直接注入计时逻辑
- 它的价值在于作为可信锚点——一旦写入,即代表该次实例化已完成且结果已固化
在初始化链路中埋点并落库到只读字段
以 Reader Kit 的 PhonePC/2in1Tablet 构造函数为例,可在其实现中加入毫秒级时间戳采集:
- 在构造函数入口记录
start = performance.now() - 在构造完成、关键属性(如 dataId)生成后,计算耗时:
duration = performance.now() - start - 将
duration作为只读元数据附加到实例(例如挂载为this._initDurationMs,设为 getter-only 属性) - 若框架支持,也可将该耗时写入统一监控日志或上报至审计服务端,同时确保日志条目本身带不可篡改时间戳和 traceID
构建自动化审计流水线
只读属性的价值在规模化读取时才真正释放。建议搭建三层轻量审计机制:
-
采集层:通过项目构建插件或运行时代理(如 WebView2 的 DevTools 协议监听),自动识别所有继承自
ReaderCoreIdentity的组件实例,并提取其_initDurationMs或等效只读耗时字段 - 聚合层:按组件类型(nodeType)、设备形态(PhonePC / 2in1Tablet)、页面加载阶段(首屏/懒加载)分组统计 P50/P90 耗时、异常值(>300ms)占比
- 告警层:当某类微任务连续 3 次 P90 超过阈值,或单次耗时突破 1s,自动触发 PR 检查注释或飞书告警,附带调用栈快照与前后资源加载水位
规避常见陷阱
实践中容易忽略的关键细节:
- 避免在构造函数中执行 DOM 操作或网络请求——这会污染耗时数据,应移至
onReady等生命周期钩子 - 注意多线程环境(如 WebView2 多进程)下
performance.now()的时钟一致性,优先使用同一进程内采集 - 只读字段若由服务端下发(如预渲染 dataId),需确认耗时是否包含网络 RTT;建议客户端侧单独测纯构造耗时,服务端侧另做 SSR 渲染耗时审计
- 不要把“只读”误解为“不可观测”——它恰恰是审计信任链的终点:你信任它,是因为它不可被运行时逻辑随意覆盖










