性能监控与 profiling 工具
性能监控是优化工作的前提,掌握专业工具才能精准定位性能瓶颈。
核心性能指标
Web Vitals
Google定义的核心性能指标:
| 指标 | 说明 | 目标值 |
|---|---|---|
| LCP | 最大内容渲染时间 | ≤2.5秒 |
| FID | 首次输入延迟 | ≤100ms |
| CLS | 累积布局偏移 | ≤0.1 |
| TTFB | 首字节时间 | ≤600ms |
| INP | 交互响应时间 | ≤200ms |
指标测量
JavaScript
// 使用web-vitals库
import { getLCP, getFID, getCLS, getTTFB, getINP } from 'web-vitals';
getLCP(console.log); // 最大内容渲染时间
getFID(console.log); // 首次输入延迟
getCLS(console.log); // 累积布局偏移
getTTFB(console.log); // 首字节时间
getINP(console.log); // 交互响应时间
// 上报数据
function sendToAnalytics(metric) {
const body = JSON.stringify({
name: metric.name,
value: metric.value,
id: metric.id,
delta: metric.delta
});
navigator.sendBeacon('/analytics', body);
}
getLCP(sendToAnalytics);
getFID(sendToAnalytics);
getCLS(sendToAnalytics);
Performance API
JavaScript
// 页面加载性能
const timing = performance.timing;
const metrics = {
// DNS查询
dns: timing.domainLookupEnd - timing.domainLookupStart,
// TCP连接
tcp: timing.connectEnd - timing.connectStart,
// 请求响应
request: timing.responseEnd - timing.requestStart,
// DOM解析
domParse: timing.domInteractive - timing.responseEnd,
// DOM完成
domComplete: timing.domComplete - timing.domInteractive,
// 页面加载总时间
total: timing.loadEventEnd - timing.navigationStart
};
// 使用PerformanceObserver
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach(entry => {
console.log(entry.name, entry.duration);
});
});
observer.observe({ entryTypes: ['measure', 'resource', 'paint'] });
// 自定义测量
performance.mark('start-operation');
// ... 操作代码
performance.mark('end-operation');
performance.measure('operation', 'start-operation', 'end-operation');
Chrome DevTools
Performance面板
JavaScript
操作步骤:
1. 打开DevTools → Performance
2. 点击录制按钮
3. 执行页面操作
4. 停止录制分析
关键分析点:
- Main线程活动:JS执行、DOM操作、样式计算
- Network:请求瀑布图
- GPU:合成层绘制
- Layout/Paint:重排重绘事件
JavaScript
// 识别长任务(>50ms)
// Performance面板中红色标记的任务
// 分析火焰图
// 黄色:JS执行
// 绿色:渲染
// 蓝色:网络请求
Memory面板
Bash
// 内存分析流程
1. DevTools → Memory
2. 选择分析类型
- Heap snapshot:堆快照
- Allocation timeline:分配时序
- Allocation sampling:分配采样
3. 查看对象分布、引用关系
// 常见问题
- Detached DOM nodes:脱离DOM树的元素
- Object retained size:对象保留大小
- GC roots:垃圾回收根节点
Rendering面板
JavaScript
开启方式:DevTools → More tools → Rendering
关键检测项:
- Paint flashing:重绘区域高亮(绿色)
- Layout shift regions:布局抖动区域(蓝色)
- Layer borders:合成层边界(橙色)
- FPS meter:帧率显示
Network面板
JavaScript
关键指标:
- TTFB:首字节时间
- Content Download:下载时间
- Size:资源大小
- Waterfall:请求顺序
优化建议:
- 关键资源优先加载
- 减少请求瀑布
- 启用压缩缓存
Lighthouse自动化检测
基础使用
JavaScript
# Chrome DevTools运行
DevTools → Lighthouse → Generate report
# CLI运行
npm install -g lighthouse
lighthouse https://example.com --output html --output-path report.html
# Node.js集成
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
async function runLighthouse(url) {
const chrome = await chromeLauncher.launch();
const options = {
port: chrome.port,
output: 'json'
};
const result = await lighthouse(url, options);
await chrome.kill();
return result;
}
报告解读
JavaScript
五大维度:
1. Performance(性能)
- LCP、FID、CLS等核心指标
- 优化建议
2. Accessibility(无障碍)
- ARIA标签
- 语义化HTML
3. Best Practices(最佳实践)
- HTTPS使用
- 控制台错误
4. SEO(搜索引擎优化)
- meta标签
- robots.txt
5. PWA(渐进式应用)
- Service Worker
- manifest.json
CI集成
JavaScript
// GitHub Actions集成
// .github/workflows/performance.yml
name: Performance Check
on: [push]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: treosh/lighthouse-ci-action@v9
with:
urls: 'https://example.com'
budgetPath: './budget.json'
// 性能预算配置
// budget.json
[
{
"path": "/",
"budgets": [
{
"resourceType": "script",
"budget": 100 // KB限制
},
{
"metric": "first-contentful-paint",
"budget": 2 // 秒限制
}
]
}
]
实时监控方案
自定义监控SDK
text
class PerformanceMonitor {
constructor() {
this.metrics = {};
this.init();
}
init() {
this.observePaint();
this.observeLayoutShift();
this.observeLongTasks();
this.observeResources();
}
observePaint() {
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
if (entry.name === 'first-paint') {
this.metrics.fp = entry.startTime;
}
if (entry.name === 'first-contentful-paint') {
this.metrics.fcp = entry.startTime;
}
});
});
observer.observe({ entryTypes: ['paint'] });
}
observeLayoutShift() {
let clsValue = 0;
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
});
this.metrics.cls = clsValue;
});
observer.observe({ entryTypes: ['layout-shift'] });
}
observeLongTasks() {
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
this.reportLongTask(entry);
});
});
observer.observe({ entryTypes: ['longtask'] });
}
observeResources() {
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
if (entry.initiatorType === 'script') {
this.metrics[entry.name] = entry.duration;
}
});
});
observer.observe({ entryTypes: ['resource'] });
}
report() {
return this.metrics;
}
}
错误监控集成
text
// 全局错误捕获
window.addEventListener('error', (event) => {
const errorInfo = {
type: 'error',
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
timestamp: Date.now()
};
sendError(errorInfo);
});
// Promise错误
window.addEventListener('unhandledrejection', (event) => {
const errorInfo = {
type: 'unhandledrejection',
message: event.reason,
timestamp: Date.now()
};
sendError(errorInfo);
});
// 资源加载错误
window.addEventListener('error', (event) => {
if (event.target !== window) {
const errorInfo = {
type: 'resourceError',
tagName: event.target.tagName,
src: event.target.src,
timestamp: Date.now()
};
sendError(errorInfo);
}
}, true);
性能预算
配置预算
text
// 资源预算
const budgets = {
totalJS: 200 * 1024, // 总JS 200KB
totalCSS: 50 * 1024, // 总CSS 50KB
totalImages: 500 * 1024, // 总图片 500KB
// 时间预算
LCP: 2500, // 2.5秒
FID: 100, // 100ms
CLS: 0.1
};
// 检查预算
function checkBudget() {
const metrics = getMetrics();
if (metrics.LCP > budgets.LCP) {
console.warn('LCP超出预算:', metrics.LCP);
}
if (metrics.totalJS > budgets.totalJS) {
console.warn('JS总大小超出预算:', metrics.totalJS);
}
}
预算告警
text
// CI预算检查
// performance-budget.json
{
"budgets": [
{
"metric": "first-contentful-paint",
"max": 2000
},
{
"metric": "interactive",
"max": 3000
},
{
"resourceType": "script",
"max": 150
}
]
}
// Webpack预算插件
const PerformanceBudgetPlugin = require('webpack-performance-budget');
module.exports = {
plugins: [
new PerformanceBudgetPlugin({
budgets: {
'bundle.js': 200 * 1024,
'vendor.js': 100 * 1024
}
})
]
};
要点总结
- Web Vitals:LCP、FID、CLS是Google核心指标
- Performance API:测量页面加载、资源、自定义操作
- DevTools Performance:火焰图分析JS执行、渲染瓶颈
- DevTools Memory:检测内存泄漏、对象分布
- Lighthouse:自动化全方位检测报告
- 性能预算:设定阈值,CI集成自动告警
存放路径:articles/JS/专家/高级性能分析/性能监控与 profiling 工具.md
📝 发现内容有误?点击此处直接编辑