前端监控¶
📚 章节目标¶
本章节将全面介绍前端监控的各种技术和工具,包括Sentry、Lighthouse、Web Vitals、APM等,帮助学习者掌握前端监控的核心方法。
学习目标¶
- 理解前端监控的核心概念
- 掌握Sentry错误监控
- 掌握Lighthouse性能分析
- 掌握Web Vitals性能监控
- 掌握APM性能监控
- 理解监控最佳实践
🔍 前端监控概述¶
1. 监控类型¶
JavaScript
// 前端监控类型
// 1. 错误监控 - 捕获和上报错误
// 2. 性能监控 - 监控应用性能
// 3. 行为监控 - 监控用户行为
// 4. 业务监控 - 监控业务指标
// 错误监控示例
window.addEventListener('error', (event) => {
console.error('Error:', event.error);
// 上报错误
reportError(event.error);
});
// 性能监控示例
const perfData = performance.getEntriesByType('navigation')[0];
console.log('Page load time:', perfData.loadEventEnd - perfData.fetchStart);
2. 监控指标¶
JavaScript
// 核心监控指标
// 1. 错误率 - 错误次数 / PV
// 2. 性能指标 - LCP, INP, CLS
// 3. 转化率 - 转化次数 / PV
// 4. 留存率 - 活跃用户 / 总用户
// 5. 用户满意度 - 用户评分
// 计算错误率
const errorRate = (errorCount / pageViews) * 100;
console.log(`Error rate: ${errorRate}%`);
🚨 Sentry错误监控¶
1. Sentry基础¶
1.1 基本配置¶
JavaScript
// 安装Sentry(v8+ 无需单独安装 @sentry/tracing)
npm install @sentry/react
// 配置Sentry
import * as Sentry from '@sentry/react';
Sentry.init({
dsn: 'https://example@sentry.io/project-id',
integrations: [
Sentry.browserTracingIntegration({
tracePropagationTargets: ['localhost', 'https://api.example.com'],
}),
],
tracesSampleRate: 1.0,
environment: process.env.NODE_ENV,
release: 'my-project@1.0.0',
});
// 在React中使用
import { ErrorBoundary } from '@sentry/react';
function App() {
return (
<ErrorBoundary fallback={<div>Something went wrong</div>}>
<MyComponent />
</ErrorBoundary>
);
}
1.2 错误捕获¶
JavaScript
// 捕获全局错误
window.addEventListener('error', (event) => {
Sentry.captureException(event.error);
});
// 捕获未处理的Promise拒绝
window.addEventListener('unhandledrejection', (event) => {
Sentry.captureException(event.reason);
});
// 手动捕获错误
try {
doSomething();
} catch (error) {
Sentry.captureException(error);
}
// 捕获React错误
class ErrorBoundary extends React.Component {
componentDidCatch(error, errorInfo) {
Sentry.captureException(error, {
contexts: {
react: {
componentStack: errorInfo.componentStack,
},
},
});
}
}
2. Sentry高级特性¶
2.1 用户信息¶
JavaScript
// 设置用户信息
Sentry.setUser({
id: '123',
username: 'john_doe',
email: 'john@example.com',
});
// 清除用户信息
Sentry.setUser(null);
// 设置标签
Sentry.setTag('page', 'home');
Sentry.setTag('userType', 'premium');
// 设置额外数据
Sentry.setExtra('customData', {
featureFlag: true,
experiment: 'A',
});
2.2 自定义事件¶
JavaScript
// 发送自定义事件
Sentry.captureMessage('Custom message', 'info');
// 发送自定义错误
Sentry.captureException(new Error('Custom error'));
// 发送带上下文的事件
Sentry.captureException(error, {
level: 'error',
tags: {
section: 'checkout',
},
extra: {
cartItems: 5,
totalAmount: 100,
},
});
// 发送面包屑
Sentry.addBreadcrumb({
message: 'User clicked button',
category: 'user',
level: 'info',
});
🚀 Lighthouse性能分析¶
1. Lighthouse基础¶
1.1 命令行使用¶
Bash
# 安装Lighthouse
npm install -g lighthouse
# 运行Lighthouse
lighthouse https://example.com --output html --output-path report.html
# 运行特定类别
lighthouse https://example.com --only-categories=performance
# 运行多次取平均值
for i in {1..5}; do # Shell for循环
lighthouse https://example.com --output json --output-path "report-$i.json"
done
1.2 Node.js API¶
JavaScript
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
async function runLighthouse(url) {
const chrome = await chromeLauncher.launch({
chromeFlags: ['--headless'],
});
const options = {
logLevel: 'info',
output: 'html',
onlyCategories: ['performance'],
port: chrome.port,
};
const runnerResult = await lighthouse(url, options);
await chrome.kill();
return runnerResult;
}
runLighthouse('https://example.com').then((results) => {
console.log('Performance score:', results.lhr.categories.performance.score * 100);
});
2. Lighthouse配置¶
2.1 自定义配置¶
JavaScript
// lighthouse-config.js
module.exports = {
extends: 'lighthouse:default',
settings: {
onlyCategories: ['performance', 'accessibility', 'best-practices', 'seo'],
throttling: {
rttMs: 40,
throughputKbps: 10240,
cpuSlowdownMultiplier: 1,
requestLatencyMs: 0,
downloadThroughputKbps: 0,
uploadThroughputKbps: 0,
},
emulatedFormFactor: 'desktop',
screenEmulation: {
mobile: false,
width: 1920,
height: 1080,
deviceScaleFactor: 1,
disabled: false,
},
},
};
// 使用自定义配置
lighthouse https://example.com --config-path=lighthouse-config.js
2.2 CI集成¶
YAML
# .github/workflows/lighthouse.yml
name: Lighthouse CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lighthouse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Run Lighthouse
uses: treosh/lighthouse-ci-action@v9
with:
urls: |
https://example.com
uploadArtifacts: true
temporaryPublicStorage: true
📊 Web Vitals性能监控¶
1. Web Vitals基础¶
1.1 核心指标¶
JavaScript
import { onCLS, onINP, onLCP } from 'web-vitals';
// 监控CLS
onCLS((metric) => {
console.log('CLS:', metric.value);
// 发送到分析服务
analytics.track('CLS', {
value: metric.value,
id: metric.id,
});
});
// 监控INP(替代已废弃的FID,2024年3月起成为Core Web Vital)
onINP((metric) => {
console.log('INP:', metric.value);
analytics.track('INP', {
value: metric.value,
id: metric.id,
});
});
// 监控LCP
onLCP((metric) => {
console.log('LCP:', metric.value);
analytics.track('LCP', {
value: metric.value,
id: metric.id,
});
});
1.2 所有Web Vitals¶
JavaScript
import {
onCLS,
onFCP,
onLCP,
onTTFB,
onINP,
} from 'web-vitals';
// 监控所有指标(INP 已于 2024年3月取代 FID 成为 Core Web Vital)
onCLS(sendToAnalytics);
onFCP(sendToAnalytics);
onLCP(sendToAnalytics);
onTTFB(sendToAnalytics);
onINP(sendToAnalytics);
function sendToAnalytics(metric) {
const data = {
name: metric.name,
value: metric.value,
id: metric.id,
delta: metric.delta,
rating: metric.rating,
};
// 发送到分析服务
analytics.track('Web Vitals', data);
// 发送到自定义端点
fetch('/api/analytics', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
},
});
}
2. Web Vitals优化¶
2.1 LCP优化¶
JavaScript
// 优化LCP的策略
// 1. 预加载关键资源
<link rel="preload" href="/images/hero.jpg" as="image">
<link rel="preload" href="/fonts/main.woff2" as="font">
// 2. 优化图片
<img
src="image.webp"
srcset="image-small.webp 400w, image-medium.webp 800w"
sizes="(max-width: 600px) 400px, 800px"
loading="eager"
decoding="async"
>
// 3. 优化关键CSS
<style>
/* 内联关键CSS */
</style>
<link rel="preload" href="/styles/main.css" as="style">
2.2 INP优化¶
JavaScript
// 优化INP(Interaction to Next Paint)的策略
// 1. 减少JavaScript执行时间
// 2. 代码分割和懒加载
// 3. 使用Web Workers
// Web Worker示例
const worker = new Worker('worker.js');
worker.postMessage({ data: largeData });
worker.onmessage = (e) => { // 箭头函数:简洁的函数语法
console.log('Result:', e.data);
};
// worker.js
self.onmessage = (e) => {
const result = processData(e.data);
self.postMessage(result);
};
2.3 CLS优化¶
JavaScript
// 优化CLS的策略
// 1. 为图片和视频设置尺寸
<img
src="image.jpg"
width="800"
height="600"
alt="Description"
>
// 2. 为动态内容预留空间
<div style="min-height: 200px;">
<!-- 动态内容 -->
</div>
// 3. 使用transform和opacity进行动画
.animated-element {
transition: transform 0.3s ease, opacity 0.3s ease;
}
📈 APM性能监控¶
1. APM基础¶
1.1 基本配置¶
JavaScript
// 使用New Relic
import * as newrelic from 'newrelic';
newrelic.initializeAgent({
appName: 'my-app',
licenseKey: 'your-license-key',
distributedTracingEnabled: true,
});
// 使用Datadog
import { datadogRum } from '@datadog/browser-rum';
datadogRum.init({
applicationId: 'your-app-id',
clientToken: 'your-client-token',
site: 'datadoghq.com',
service: 'my-app',
env: 'production',
sessionSampleRate: 100,
trackInteractions: true,
});
// 使用Dynatrace
import { dtrum } from '@dynatrace/browser-agent';
dtrum.init({
applicationId: 'your-app-id',
beaconURL: 'https://your-beacon-url',
});
2.2 性能追踪¶
JavaScript
// 追踪用户操作
datadogRum.addAction('button_click', {
buttonName: 'submit',
page: 'checkout',
});
// 追踪错误
datadogRum.addError(new Error('Something went wrong'), {
component: 'CheckoutForm',
action: 'submit',
});
// 追踪资源
datadogRum.addResourceTiming({
name: '/api/users',
duration: 150,
size: 1024,
});
// 追踪自定义指标
datadogRum.addTiming('custom_metric', 100);
2. APM高级特性¶
2.1 分布式追踪¶
JavaScript
// 追踪API请求
import { trace } from '@opentelemetry/api';
const tracer = trace.getTracer('my-app'); // const不可重新赋值;let块级作用域变量
async function fetchUsers() { // async定义异步函数;await等待Promise完成
const span = tracer.startSpan('fetchUsers', {
attributes: {
'http.method': 'GET',
'http.url': '/api/users',
},
});
try { // try/catch捕获异常
const response = await fetch('/api/users'); // await等待异步操作完成
span.setStatus({ code: SpanStatusCode.OK });
return response.json();
} catch (error) {
span.recordException(error);
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
}
2.2 自定义指标¶
JavaScript
// 发送自定义指标
fetch('/api/analytics', {
method: 'POST',
body: JSON.stringify({
metric: 'checkout_duration',
value: 5000,
tags: {
payment_method: 'credit_card',
user_type: 'premium',
},
}),
});
// 发送自定义事件
fetch('/api/analytics', {
method: 'POST',
body: JSON.stringify({
event: 'purchase_completed',
properties: {
amount: 100,
items: 5,
},
}),
});
📝 练习题¶
1. 基础题¶
题目1:配置Sentry错误监控
2. 进阶题¶
题目2:实现Web Vitals监控
JavaScript
// 实现Web Vitals监控
import { onCLS, onINP, onLCP } from 'web-vitals';
function sendToAnalytics(metric) {
// 发送到分析服务
}
// 监控核心指标
3. 面试题¶
题目3:解释Core Web Vitals的含义
JavaScript
// 答案要点:
// 1. LCP (Largest Contentful Paint) - 最大内容绘制,衡量页面主要内容加载时间
// 2. INP (Interaction to Next Paint) - 交互到下一次绘制,衡量页面整体交互响应性
// (2024年3月起取代 FID 成为 Core Web Vital)
// 3. CLS (Cumulative Layout Shift) - 累积布局偏移,衡量页面布局稳定性
// 4. 目标值:LCP < 2.5s, INP < 200ms, CLS < 0.1
🎯 本章总结¶
本章节全面介绍了前端监控的各种技术和工具,包括Sentry、Lighthouse、Web Vitals、APM等。关键要点:
- 监控类型:理解错误监控、性能监控、行为监控
- Sentry:掌握Sentry错误监控和高级特性
- Lighthouse:掌握Lighthouse性能分析和CI集成
- Web Vitals:掌握Web Vitals性能监控和优化
- APM:掌握APM性能监控和分布式追踪
- 最佳实践:理解监控最佳实践和指标分析
下一步将深入学习微前端架构。