1. 题目
一个全球访问的单页应用需要收集真实用户性能数据,用于比较不同设备、网络和版本的体验。你需要采集 LCP、资源加载和长任务,同时限制每个页面会话的上报量。请设计基于 PerformanceObserver 的采集器,并说明它如何处理页面加载前已经产生的条目、缓冲区丢失、跨域资源和 SPA 路由切换。
2. 约束与澄清
- 先定义每个指标的时间范围:初始文档、软导航,还是一次完整会话。
- 设定采样率、每类条目上限、批量上报大小和失败重试策略,避免采集器影响页面。
- 区分浏览器支持差异与数据缺失;缺失值必须带原因,不应默认为零。
- 明确资源 URL、用户标识和查询维度的隐私边界,避免把完整 URL 或敏感参数直接上报。
3. 核心概念
PerformanceObserver 通过观察指定的 entry type 接收性能条目;buffered: true 可补取观察器建立前已经记录的条目。资源、长任务、绘制和 LCP 等类型有各自的缓冲区限制,回调还可以收到 droppedEntriesCount,用于发现缓冲区已丢弃条目。LCP 是加载期间最大的图像或文本块绘制时间,用户交互后不应继续把后续内容当作初始 LCP。跨域资源若没有合适的 Timing-Allow-Origin 响应头,计时信息可能被限制或缺失。
4. 参考实现
startCollector():
session = createSessionId()
observe("largest-contentful-paint", {buffered: true})
observe("resource", {buffered: true})
observe("longtask", {buffered: true})
observe(type, options):
if type not in PerformanceObserver.supportedEntryTypes:
markUnsupported(type)
return
observer = new PerformanceObserver((list, _, dropped) =>
appendSanitized(list.getEntries())
if dropped > 0: markDropped(type, dropped)
flushWhenBatchIsReady()
)
observer.observe({type, ...options})
onSoftNavigation(route):
closePreviousView(route)
resetViewScopedMetrics()初始化时为每类条目注册独立观察器,优先使用 buffered 补取早期记录;回调只保留需要的字段、裁剪 URL 参数并按批次发送。每个视图保存观察器建立时间、路由和版本,软导航时结束旧视图并重置视图级指标;会话级资源或错误计数则使用明确的去重键继续累计。
5. 数据质量与成本取舍
采样率越高,分位数更稳定,但网络和存储成本也越高。可以对 LCP、长任务保留较高样本,对资源条目采用头部采样或仅保留慢资源。单个 resource 缓冲区默认最多保存 250 条,采集器应在页面生命周期内及时消费并记录丢失数量,而不是无限提高上报频率。客户端批量发送失败时只做有限重试,并在下次页面访问时丢弃过期批次,避免本地队列拖慢启动。
6. 验证与观测
- 在观察器建立前制造条目,验证
buffered能补取;在大量资源页面验证droppedEntriesCount告警。 - 用跨域资源分别测试有、无
Timing-Allow-Origin时的字段差异,并确认缺失原因可区分。 - 对初始加载、软导航、后台恢复和页面隐藏分别回放,检查 LCP 与资源条目不会跨视图重复归因。
- 监控采集器自身的 CPU、内存、上报字节数、批次失败率、条目丢失率和支持率。
7. 常见误区
- 只在
load事件后创建观察器,导致早期 LCP 或资源条目永远缺失。 - 看到
droppedEntriesCount后静默丢弃,却继续把不完整样本当成完整分布。 - 把跨域资源的受限计时当作真实的零延迟,污染性能分位数。
- SPA 每次路由都新建观察器却不关闭旧观察器,造成重复上报和内存泄漏。
8. 面试评分点
能正确使用观察器生命周期
应说明 buffered、supportedEntryTypes、观察器关闭与软导航边界,避免早期丢失和重复统计。
能处理缓冲区与跨域限制
应监控 droppedEntriesCount,了解资源缓冲区上限,并用 Timing-Allow-Origin 解释跨域字段缺失。
能设计可控的采样与上报
应按指标价值分配采样率、条目上限和批量策略,说明失败重试不会反过来拖慢页面。
能验证数据可信度
应覆盖早期条目、海量资源、跨域、软导航和后台恢复场景,同时观测采集器自身开销与丢失率。