Performance API是现代浏览器提供的一组接口,用于精确测量网页和Web应用的性能。以下是使用Performance API监控前端性能的详细指南:
// 获取页面加载总时间
const loadTime = window.performance.timing.loadEventEnd - window.performance.timing.navigationStart;
console.log(`页面加载总时间: ${loadTime}ms`);
// 分解各个阶段时间
const timing = window.performance.timing;
const metrics = {
DNS查询时间: timing.domainLookupEnd - timing.domainLookupStart,
TCP连接时间: timing.connectEnd - timing.connectStart,
请求响应时间: timing.responseEnd - timing.requestStart,
DOM解析时间: timing.domComplete - timing.domInteractive,
白屏时间: timing.responseStart - timing.navigationStart,
DOM加载完成时间: timing.domContentLoadedEventEnd - timing.navigationStart,
页面完全加载时间: timing.loadEventEnd - timing.navigationStart
};
console.table(metrics);
const [entry] = performance.getEntriesByType("navigation");
console.log({
页面加载总时间: entry.loadEventEnd - entry.startTime,
DNS时间: entry.domainLookupEnd - entry.domainLookupStart,
TCP时间: entry.connectEnd - entry.connectStart,
请求时间: entry.responseEnd - entry.requestStart,
DOM解析时间: entry.domComplete - entry.domInteractive
});
// 获取所有资源加载信息
const resources = performance.getEntriesByType("resource");
resources.forEach(resource => {
console.log(`${resource.name} 加载耗时: ${resource.duration}ms`);
});
// 计算平均资源加载时间
const avgResourceLoadTime = resources.reduce((acc, curr) => acc + curr.duration, 0) / resources.length;
console.log(`平均资源加载时间: ${avgResourceLoadTime}ms`);
// 标记开始点
performance.mark('taskStart');
// 执行一些任务
for (let i = 0; i < 1000000; i++) { Math.sqrt(i); }
// 标记结束点
performance.mark('taskEnd');
// 测量两个标记之间的时间
performance.measure('taskDuration', 'taskStart', 'taskEnd');
// 获取测量结果
const measures = performance.getEntriesByName('taskDuration');
console.log(`任务耗时: ${measures[0].duration}ms`);
// 清除标记和测量
performance.clearMarks();
performance.clearMeasures();
function measureInteraction(eventType, elementSelector, callback) {
const element = document.querySelector(elementSelector);
element.addEventListener(eventType, function() {
const startTime = performance.now();
// 执行回调函数
if (callback) callback();
const duration = performance.now() - startTime;
console.log(`${eventType} on ${elementSelector} 耗时: ${duration}ms`);
// 可以发送到监控系统
// sendToAnalytics({event: eventType, element: elementSelector, duration});
});
}
// 使用示例
measureInteraction('click', '#submitBtn', () => {
// 处理点击逻辑
});
// 使用PerformanceObserver监控长任务(>50ms)
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`长任务耗时: ${entry.duration}ms`, entry);
// 可以发送到监控系统
}
});
observer.observe({ entryTypes: ['longtask'] });
// 使用MutationObserver监控DOM变化来估算首屏时间
let firstScreenTime = 0;
const observer = new MutationObserver(() => {
if (!firstScreenTime) {
firstScreenTime = performance.now();
console.log(`首屏渲染时间: ${firstScreenTime}ms`);
observer.disconnect();
}
});
observer.observe(document, { childList: true, subtree: true });
// 设置超时,防止某些情况下MutationObserver不触发
setTimeout(() => {
if (!firstScreenTime) {
firstScreenTime = performance.now();
console.log(`首屏渲染时间(超时): ${firstScreenTime}ms`);
observer.disconnect();
}
}, 5000);
// 监控内存使用情况
if (window.performance && performance.memory) {
setInterval(() => {
const memory = performance.memory;
console.log(`内存使用:
JS堆大小: ${memory.usedJSHeapSize / 1024 / 1024}MB / ${memory.jsHeapSizeLimit / 1024 / 1024}MB
总堆大小: ${memory.totalJSHeapSize / 1024 / 1024}MB`);
}, 10000);
}
function sendPerformanceData() {
const data = {
timestamp: new Date().toISOString(),
navigation: performance.getEntriesByType('navigation')[0],
resources: performance.getEntriesByType('resource'),
// 可以添加其他自定义指标
};
// 使用navigator.sendBeacon确保在页面卸载时也能发送数据
navigator.sendBeacon('/api/performance', JSON.stringify(data));
}
// 页面加载完成时发送
window.addEventListener('load', sendPerformanceData);
// 页面卸载前发送
window.addEventListener('beforeunload', sendPerformanceData);
浏览器兼容性:不同浏览器对Performance API的支持程度不同,建议在使用前检查兼容性或使用polyfill。
隐私考虑:收集性能数据时要注意用户隐私,确保符合GDPR等法规要求。
数据采样:对于高流量网站,考虑采样上报而非全量上报,避免服务器压力过大。
异常处理:添加适当的错误处理,防止性能监控代码本身影响页面功能。
性能开销:监控代码本身也会带来性能开销,要确保监控逻辑尽可能高效。
通过合理使用Performance API,你可以全面了解你的Web应用的性能表现,及时发现并解决性能瓶颈。