2026-05-11 04:03:38
JS实现前端性能监控的核心在于利用浏览器提供的Performance API,配合自定义监控策略和上报机制。以下是5个核心指标的监控方法及实现代码:
页面加载时间(Load Time)通过performance.timing计算从导航开始到load事件完成的时间差:
window.addEventListener('load', () => { const loadTime = performance.timing.loadEventEnd - performance.timing.navigationStart; console.log('页面加载时间:', loadTime, 'ms'); reportMetric('load_time', loadTime);});function reportMetric(name, value) { fetch('/api/metrics', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, value }) }).catch(err => console.error('上报失败:', err));}挑战:旧浏览器可能存在兼容性问题,需做降级处理。
改进:结合PerformanceObserver监听longtask事件,定位阻塞主线程的任务。
首次渲染时间(FP)与首次内容绘制时间(FCP)通过PerformanceObserver监听paint事件,获取页面首次渲染和内容绘制的时间:
new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { if (entry.name === 'first-paint') { reportMetric('first_paint', entry.startTime); } else if (entry.name === 'first-contentful-paint') { reportMetric('first_contentful_paint', entry.startTime); } }}).observe({ type: 'paint', buffered: true });挑战:字体加载可能延长FCP时间。
优化:优化关键渲染路径,例如延迟加载非关键资源。
最大内容绘制时间(LCP)监听largest-contentful-paint事件,获取视窗中最大内容元素的渲染时间:
new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { reportMetric('largest_contentful_paint', entry.startTime); }}).observe({ type: 'largest-contentful-paint', buffered: true });挑战:图片、视频等资源加载可能影响LCP。
优化:压缩图片、使用CDN加速、预加载关键资源。
首次可交互时间(TTI)结合longtask事件和load事件,判断页面在5秒内无长任务的时间点:
let lastLongTaskEndTime = 0;new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { if (entry.duration > 50) { lastLongTaskEndTime = entry.startTime + entry.duration; } }}).observe({ type: 'longtask', buffered: true });window.addEventListener('load', () => { setTimeout(() => { const tti = lastLongTaskEndTime || performance.timing.loadEventEnd; reportMetric('time_to_interactive', tti); }, 5000);});挑战:TTI计算方法复杂,不同工具可能结果不同。
改进:使用Lighthouse等工具辅助计算。
输入延迟(FID)监听first-input事件,计算用户首次交互的响应延迟:
new PerformanceObserver((entryList) => { for (const entry of entryList.getEntries()) { const fid = entry.processingStart - entry.startTime; reportMetric('first_input_delay', fid); }}).observe({ type: 'first-input', buffered: true });挑战:FID仅在用户首次交互时获取。
优化:减少JavaScript执行时间,避免阻塞主线程。
若页面使用CDN或其他域名资源,需配置以下内容以解决跨域问题:
选择工具时需考虑以下因素:
性能监控数据需通过以下步骤优化页面: