讲师中心 微信公众号
AI工具推荐 视频效率加速

如何用Performance API监控网页运行时性能?

夜宇姑娘_7445

夜宇姑娘_7445

发布时间:2025-09-22 18:19:01

|

467人浏览过

|

来源于php中文网

原创

Performance API通过window.performance提供页面加载、资源消耗及用户体验指标,利用getEntriesByType、mark/measure和PerformanceObserver监控关键性能数据,并结合批处理与异步上报优化收集效率。

如何用performance api监控网页运行时性能?

Performance API是现代浏览器提供的一套强大工具,它允许开发者在运行时深入了解网页的性能表现。简单来说,它就像是浏览器内部的“黑匣子”,能记录下从页面加载到用户交互的各种时间点和资源消耗,帮助我们精准定位性能瓶颈。

解决方案

要利用Performance API监控网页运行时性能,我们主要围绕

window.performance
对象展开。这个对象提供了一系列接口,让我们能够触及浏览器内部的计时数据。

首先,最基础的莫过于获取页面导航和加载的关键时间点。虽然

performance.timing
还在,但更推荐使用
performance.getEntriesByType('navigation')
来获取更现代、更精准的导航时间线。它会返回一个
PerformanceEntry
数组,其中包含了页面加载的详细信息,比如
domContentLoadedEventEnd
(DOM内容加载并解析完毕的时间)和
loadEventEnd
(所有资源加载完成的时间)。

// 获取导航性能数据
const navigationEntries = performance.getEntriesByType('navigation');
if (navigationEntries.length > 0) {
    const navTiming = navigationEntries[0];
    console.log('页面加载完成时间:', navTiming.loadEventEnd - navTiming.startTime, 'ms');
    console.log('DOM内容加载完成时间:', navTiming.domContentLoadedEventEnd - navTiming.startTime, 'ms');
    // 更多指标如 responseEnd, requestStart 等
}

接着是资源加载的监控,这对于识别加载慢的图片、脚本或样式表至关重要。

performance.getEntriesByType('resource')
能返回所有页面请求的资源详细信息,包括它们的加载时间、大小、发起者等。我个人觉得,这个接口是排查页面加载卡顿的利器,很多时候,意想不到的第三方脚本或者大图就是罪魁祸首。

// 获取所有资源加载性能数据
const resourceEntries = performance.getEntriesByType('resource');
resourceEntries.forEach(entry => {
    // 过滤掉一些不重要的或者非HTTP/HTTPS的资源
    if (entry.name.startsWith('http')) {
        console.log(`资源: ${entry.name}, 类型: ${entry.initiatorType}, 加载时间: ${entry.duration.toFixed(2)} ms`);
    }
});

除了浏览器自动记录的数据,我们还能通过

performance.mark()
和
performance.measure()
来自定义性能监控点。这在测量特定业务逻辑或组件渲染时间时特别有用。比如,你想知道某个复杂计算函数执行了多久,或者某个UI组件从数据获取到渲染完成用了多长时间,
User Timing API
就能派上用场。

// 自定义用户计时
performance.mark('startDataProcessing');
// 假设这里执行了一些数据处理操作
for (let i = 0; i < 1000000; i++) { Math.sqrt(i); }
performance.mark('endDataProcessing');
performance.measure('dataProcessingDuration', 'startDataProcessing', 'endDataProcessing');

// 获取自定义测量结果
performance.getEntriesByName('dataProcessingDuration').forEach(entry => {
    console.log(`自定义测量: ${entry.name}, 持续时间: ${entry.duration.toFixed(2)} ms`);
});

最后,也是我个人认为在现代前端性能监控中不可或缺的,是

PerformanceObserver
。它提供了一种异步、非侵入式的方式来监听各种性能事件,比如“长任务”(Long Tasks)、首次内容绘制(First Contentful Paint, FCP)、最大内容绘制(Largest Contentful Paint, LCP)等。这比定时去拉取
performance.getEntries()
要高效得多,而且能捕获到一些瞬时发生的性能问题。

// 监听长任务
const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
        if (entry.entryType === 'longtask') {
            console.warn('检测到长任务:', entry.name, '持续时间:', entry.duration.toFixed(2), 'ms', '在', entry.startTime.toFixed(2), 'ms时发生');
            // 可以进一步分析长任务的源头,比如其哪个脚本导致
        }
        // 也可以监听 'paint', 'largest-contentful-paint', 'layout-shift', 'resource', 'navigation' 等
    }
});
observer.observe({ entryTypes: ['longtask', 'paint', 'largest-contentful-paint', 'layout-shift'] });
// 记得在不需要时调用 observer.disconnect() 来停止监听

理解Performance API的核心指标:哪些数据最能反映用户体验?

说到用户体验,我们不能只盯着页面加载速度这一个维度。一个页面即使加载得再快,如果交互卡顿或者内容跳动,用户依然会觉得体验糟糕。在我看来,以下几个核心指标是真正能反映用户体验的:

1. 首次内容绘制 (First Contentful Paint, FCP): 这个指标衡量的是浏览器渲染出第一个DOM元素或者文本、图片的时间点。它直接反映了用户看到页面内容的第一眼有多快。FCP越短,用户就越早感受到页面正在加载,而不是一片空白。这给了用户一个即时的视觉反馈,非常重要。

2. 最大内容绘制 (Largest Contentful Paint, LCP): LCP衡量的是视口内最大的内容元素(比如一张大图、一个视频或者一个大标题)渲染完成的时间。这个指标尤其关键,因为它通常代表了页面主要内容的加载完成。用户真正关心的往往是页面上那些“大块头”内容,LCP直接反映了这些核心内容多久才呈现在他们眼前。通过

PerformanceObserver
监听
largest-contentful-paint
类型的
PerformanceEntry
可以获取。

3. 首次输入延迟 (First Input Delay, FID): FID衡量的是用户首次与页面交互(比如点击按钮、输入文本)到浏览器实际响应这些交互之间的时间。这个指标直接关系到页面的响应性。想象一下,你点击一个按钮,但页面半天没反应,这种体验无疑是糟糕透顶的。高FID通常意味着主线程被长时间的JavaScript任务阻塞了。虽然Performance API不能直接提供FID,但我们可以通过监听

longtask
来间接推断可能导致FID的问题。

4. 总阻塞时间 (Total Blocking Time, TBT): TBT是FCP到TTI(Time to Interactive,页面可交互时间)之间所有长任务(主线程阻塞超过50毫秒的任务)阻塞时间的总和。它是一个非常好的衡量页面交互响应性的指标。TBT越高,用户在页面加载完成前可能遇到的卡顿感就越强。这个指标可以通过

PerformanceObserver
收集
longtask
数据后计算得出。

5. 累计布局偏移 (Cumulative Layout Shift, CLS): CLS衡量的是页面内容在加载过程中发生的意外布局偏移的总和。你可能遇到过这样的情况:正要点击一个按钮,结果上方突然加载出一张图片,把按钮挤下去了,然后你就点错了。这种视觉上的不稳定感非常影响用户体验。虽然CLS不是直接通过

performance.timing
获取的,但
PerformanceObserver
可以监听
layout-shift
类型的
PerformanceEntry
来帮助我们计算。

这些指标,在我看来,构成了一个相对完整的用户体验画像。它们不仅仅是技术数据,更是我们理解用户“感受”页面的窗口。

如何高效地收集和分析Performance API数据,避免性能开销?

说实话,Performance API虽然强大,但如果使用不当,它本身的监控行为也可能成为性能负担。高效地收集和分析数据,关键在于策略和工具的选择。

首先,也是最核心的建议:优先使用

PerformanceObserver
。 这一点我前面也提到了,但它的重要性值得再强调一次。与传统的
performance.getEntries()
或
performance.getEntriesByType()
不同,
PerformanceObserver
是异步的、非阻塞的。它不会在主线程上执行大量计算,而是在后台默默地监听事件,当有新的性能条目产生时,再通过回调函数通知你。这极大地减少了监控本身对页面性能的影响。

// 示例:高效监听多种性能指标
const observer = new PerformanceObserver((list) => {
    const entries = list.getEntries();
    // 这里可以对收集到的entries进行批处理、过滤或发送
    console.log('新性能条目:', entries);
    // 假设我们只关心FCP和LCP
    entries.forEach(entry => {
        if (entry.entryType === 'paint' && entry.name === 'first-contentful-paint') {
            console.log('FCP:', entry.startTime.toFixed(2), 'ms');
        } else if (entry.entryType === 'largest-contentful-paint') {
            console.log('LCP:', entry.startTime.toFixed(2), 'ms');
        }
    });
});
observer.observe({ entryTypes: ['paint', 'largest-contentful-paint', 'longtask', 'resource', 'navigation'] });

其次,数据批处理和延迟上报是避免频繁网络请求的关键。你不可能每收集到一个

PerformanceEntry
就立即向后端发送一次请求。这会造成大量的网络开销,甚至阻塞主线程。一个更好的做法是,将收集到的数据暂存起来,然后在一个合适的时机(比如页面卸载前、用户不活跃时、或者每隔几秒)批量发送。
requestIdleCallback
是一个不错的选择,它允许你在浏览器空闲时执行任务。如果浏览器不支持
requestIdleCallback
,
setTimeout
也能作为备用方案。

let performanceDataBuffer = [];
const sendData = () => {
    if (performanceDataBuffer.length > 0) {
        // 使用 navigator.sendBeacon 发送数据,它在页面卸载时也能发送,且是非阻塞的
        navigator.sendBeacon('/api/performance-report', JSON.stringify(performanceDataBuffer));
        performanceDataBuffer = []; // 清空缓冲区
    }
};

const observer = new PerformanceObserver((list) => {
    performanceDataBuffer.push(...list.getEntries());
    // 考虑在空闲时发送数据
    if ('requestIdleCallback' in window) {
        requestIdleCallback(sendData);
    } else {
        setTimeout(sendData, 2000); // 备用方案,每2秒检查一次
    }
});
observer.observe({ entryTypes: ['paint', 'longtask', 'resource'] });

// 页面卸载前确保发送数据
window.addEventListener('beforeunload', sendData);

再来,按需监听和过滤数据也很重要。

PerformanceObserver
的
observe
方法接受一个
entryTypes
数组,只监听你真正关心的类型。例如,如果你的页面资源量巨大,但你只关心关键资源的加载时间,那么在
resource
类型的数据中进行二次过滤就很有必要。不要一股脑地收集所有数据,那只会增加处理负担。

根据ui图生成前端页面
根据ui图生成前端页面

将一个或多个 UI 原型图、线框图、产品截图或设计稿转换为标准化、可直接交付的 PRD 风格文档,供产品、设计、前端和测试共同使用。适用于 Codex 需要分析 PC 网页、桌面端、移动端、响应式页面、独立弹窗、表单、表格、看板、数据大屏或多页面流程截图,还原页面结构与交互,强制套用固定文档模板,抽取跨页面共享规则,或把一组原型沉淀为单页规范文档加整体业务流程文档的场景。不适用于纯视觉审美点评、代码实现、接口设计、埋点方案、竞品分析或无 UI 输入的业务需求创作。

下载

最后,在分析端进行聚合和可视化。原始的Performance API数据是大量的、离散的时间戳和持续时间。直接看这些数字意义不大。你需要一个后端服务来接收这些数据,进行聚合计算(比如平均值、中位数、百分位数),并结合图表进行可视化。这样才能从海量数据中提炼出有价值的洞察,帮助你发现趋势和瓶颈。

Performance API在真实项目中的应用场景与常见挑战是什么?

在真实的项目开发中,Performance API远不止是“看看速度”那么简单,它能解决很多实际问题,但同时也伴随着一些挑战。

应用场景:

  1. 真实用户监控 (RUM): 这是Performance API最核心的应用场景。通过在用户浏览器端收集性能数据并上报到后端,我们可以了解不同地区、不同设备、不同网络环境下用户的真实体验。这比实验室环境下的模拟测试要真实得多,能发现很多意想不到的性能问题。

  2. A/B 测试性能对比: 当我们推出新功能或优化时,可以利用Performance API对比新旧版本在FCP、LCP、TBT等指标上的表现。比如,一个新组件库的引入是否导致了更多的长任务?一个新的图片懒加载策略是否真的提升了LCP?数据会给出最直观的答案。

  3. 性能回归检测: 每次部署新代码后,RUM数据可以帮助我们快速发现性能是否出现倒退。如果某个核心指标突然恶化,那很可能就是新代码引入了性能问题,需要立即排查。这相当于给性能加了一道“安全网”。

  4. 识别第三方脚本影响: 很多时候,页面性能瓶颈不在我们自己的代码,而在引入的第三方广告、统计或客服脚本。通过

    performance.getEntriesByType('resource')
    ,我们可以清晰地看到这些第三方脚本的加载时间、执行时间,从而评估它们对页面性能的影响,并考虑优化或替换方案。

  5. 自定义业务性能追踪: 某些复杂的业务流程,比如用户从点击商品到完成支付的整个链路,可能涉及多次页面跳转和复杂交互。我们可以使用

    performance.mark()
    和
    performance.measure()
    来标记这些关键步骤,精确测量每个步骤的耗时,从而优化用户转化路径。

常见挑战:

  1. 数据量巨大与噪音: 尤其是

    resource
    类型的条目,一个复杂页面可能有几百个资源请求,如果全部收集并上报,数据量会非常庞大。而且,有些数据可能只是噪音,对核心问题分析帮助不大。如何有效过滤、采样和聚合数据是需要解决的问题。

  2. 浏览器兼容性与API差异: 尽管核心的Performance API支持度很好,但一些较新的API(比如

    layout-shift
    或某些更详细的
    PerformanceEntry
    属性)在不同浏览器版本之间可能存在差异。这意味着你的监控代码需要考虑兼容性,或者只针对主流浏览器进行数据收集。

  3. 网络和设备环境的复杂性: 用户的网络状况(Wi-Fi、4G、5G)、设备性能(高端机、低端机)以及后台运行的其他应用都会影响页面性能。纯粹的Performance API数据可能无法直接反映这些外部因素。在分析数据时,需要结合用户环境信息进行归一化和分层分析。

  4. 数据解读与行动转化: 收集到大量数据后,如何将其转化为有意义的洞察和可执行的优化建议,是最大的挑战。原始数据往往是冰冷的数字,需要经验和工具来帮助我们理解这些数字背后真正的问题。例如,LCP变慢了,是图片太大?还是JS阻塞了渲染?这需要进一步的分析和排查。

  5. 监控本身的开销: 尽管

    PerformanceObserver
    是非阻塞的,但如果你的回调函数中执行了大量复杂的计算或同步操作,仍然可能对主线程造成负担。设计监控方案时,要始终警惕监控代码本身对页面性能的影响。

  6. 隐私与数据安全: 在收集用户性能数据时,必须注意保护用户隐私,遵守相关法规(如GDPR、CCPA)。确保收集的数据是匿名的、不包含个人身份信息的,并且告知用户数据收集的目的。

总的来说,Performance API是一个强大的工具,但它不是万能药。它需要我们有清晰的监控目标、合理的实现策略和深入的数据分析能力,才能真正发挥其价值,为用户提供更流畅、更愉悦的网页体验。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.12.20

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3188

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

5069

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3829

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

466

2026.01.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4398

2023.08.10

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

4536

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1375

2023.07.28

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

100

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.4万人学习

Bootstrap4.x---十天精品课堂
Bootstrap4.x---十天精品课堂

共22课时 | 2.4万人学习

Javascript趣味课堂
Javascript趣味课堂

共49课时 | 12.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn