前端监控实战:构建可观测的前端应用
为什么需要前端监控
很多团队还在依赖用户反馈来发现线上问题,这就像在没有监控的仓库里存放贵重物品——东西丢了都不知道。当页面频繁崩溃却无人知晓时,开发团队实际上是在做猜谜游戏。
常见误区
没有错误捕获的代码,就像在黑暗中开车。一旦出事,连事故现场都找不到。
// 反面教材:缺乏错误处理
function App() {
const [data, setData] = React.useState([]);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch('/api/data');
const result = await response.json();
setData(result);
} catch (error) {
// 仅打印日志,未上报,生产环境难以追踪
console.error('Error fetching data:', error);
}
}
fetchData();
}, []);
return (
<div>
{data.map(item => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
export default App;
最佳实践方案
1. 错误追踪(Sentry)
引入 Sentry 是建立基础监控的第一步。它能自动捕获 JavaScript 异常、Promise 拒绝以及资源加载失败。
初始化配置
// src/index.js
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';
Sentry.init({
dsn: 'YOUR_SENTRY_DSN',
integrations: [new BrowserTracing()],
tracesSampleRate: 1.0,
});
错误边界组件
React 应用必须包裹错误边界,防止整个应用因单个组件报错而白屏。
// src/ErrorBoundary.jsx
import React from 'react';
import * as Sentry from '@sentry/react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// 将错误详情上报至 Sentry
Sentry.captureException(error, { extra: errorInfo });
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
使用方式
// src/App.jsx
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
function App() {
return (
<ErrorBoundary>
<div> {/* 应用内容 */} </div>
</ErrorBoundary>
);
}
export default App;
2. 性能监控
除了功能正确性,用户体验同样重要。Web Vitals 提供了核心网页指标的标准测量方法。
// 使用 Web Vitals
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
function sendToAnalytics({ name, delta, id }) {
// 实际项目中应发送到你的分析服务
console.log(name, delta, id);
navigator.sendBeacon('/analytics', JSON.stringify({ name, delta, id }));
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);
配合 Lighthouse 进行定期审计,能更直观地发现性能瓶颈。
3. 用户行为分析
了解用户如何与产品交互,有助于定位业务层面的问题。Google Analytics 是常用的选择。
集成脚本
<!-- index.html -->
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'GA_MEASUREMENT_ID');
</script>
自定义事件追踪
function trackEvent(eventName, eventParams) {
gtag('event', eventName, eventParams);
}
// 使用示例
<button onClick={() => trackEvent('button_click', { button_name: 'submit' })}>
提交
</button>
4. 结构化日志
在生产环境中,随意打印 console.log 既影响性能又难以检索。建议封装统一的日志工具。
// 配置日志级别
const LOG_LEVELS = {
ERROR: 0,
WARN: 1,
INFO: 2,
DEBUG: 3,
};
let currentLevel = LOG_LEVELS.INFO;
function log(level, message, data) {
if (level <= currentLevel) {
const timestamp = new Date().toISOString();
const levelName = Object.keys(LOG_LEVELS)[level];
const logMessage = `[${timestamp}] [${levelName}] ${message}`;
switch (level) {
case LOG_LEVELS.ERROR:
console.error(logMessage, data);
// 此处可接入后端日志服务
break;
case LOG_LEVELS.WARN:
console.warn(logMessage, data);
break;
case LOG_LEVELS.INFO:
console.info(logMessage, data);
break;
case LOG_LEVELS.DEBUG:
console.debug(logMessage, data);
break;
}
}
}
// 使用示例
log(LOG_LEVELS.ERROR, 'Failed to fetch data', { error: 'Network error' });
log(LOG_LEVELS.INFO, 'User logged in', { userId: 123 });
结语
做好前端监控,意味着让应用在阳光下运行。任何异常都能被及时捕获,性能瓶颈能被精准定位。这不仅是技术的完善,更是对用户负责的态度。

