前端监控:别让你的应用在黑暗中运行

前端监控:别让你的应用在黑暗中运行

毒舌时刻

这应用运行得跟幽灵似的,出了问题都不知道。

各位前端同行,咱们今天聊聊前端监控。别告诉我你还在等用户反馈问题,那感觉就像在没有监控的仓库里放贵重物品——能放,但丢了都不知道。

为什么你需要前端监控

最近看到一个项目,用户反映页面经常崩溃,但开发团队根本不知道问题出在哪里。我就想问:你是在做应用还是在做猜谜游戏?

反面教材

// 反面教材:没有监控 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 监控 // 1. 安装依赖 // npm install @sentry/react @sentry/tracing // 2. 初始化 // src/index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import * as Sentry from '@sentry/react'; import { BrowserTracing } from '@sentry/tracing'; Sentry.init({ dsn: 'YOUR_SENTRY_DSN', integrations: [new BrowserTracing()], tracesSampleRate: 1.0, }); ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); // 3. 错误边界 // 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.captureException(error, { extra: errorInfo }); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } export default ErrorBoundary; // 4. 使用错误边界 // src/App.jsx import React from 'react'; import ErrorBoundary from './ErrorBoundary'; function App() { return ( <ErrorBoundary> <div> {/* 应用内容 */} </div> </ErrorBoundary> ); } export default App; 

2. 性能监控

// 正确姿势:性能监控 // 1. 使用 Lighthouse // npm install -g lighthouse // lighthouse https://example.com // 2. 使用 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); 

3. 用户行为监控

// 正确姿势:用户行为监控 // 1. 使用 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> // 2. 自定义事件 function trackEvent(eventName, eventParams) { gtag('event', eventName, eventParams); } // 使用 <button onClick={() => trackEvent('button_click', { button_name: 'submit' })}> 提交 </button> 

4. 日志监控

// 正确姿势:日志监控 // 1. 配置日志级别 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 logMessage = `[${timestamp}] [${Object.keys(LOG_LEVELS)[level]}] ${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 }); 

毒舌点评:这才叫前端监控,让你的应用在阳光下运行,任何问题都逃不过你的眼睛。

Read more

GHCTF2025-WEB题解:如何用SSTI绕过WAF黑名单(附实战payload)

从GHCTF2025实战出发:深度拆解SSTI黑名单绕过策略与高阶Payload构造 最近在GHCTF2025的WEB赛道上,一道看似简单的文件上传题目,却让不少选手陷入了“知道有洞,但payload总被拦截”的困境。这道题表面上是文件上传,实际上却是一场针对SSTI(服务器端模板注入)绕过能力的深度考验。我在实际测试中发现,很多选手能够快速识别出SSTI漏洞的存在,但在面对严格的黑名单过滤时,却往往束手无策,反复尝试的payload都被WAF无情拦截。 这种情况在真实的渗透测试和CTF比赛中并不少见。WAF(Web应用防火墙)的过滤规则越来越智能,传统的{ {7*7}}测试虽然能确认漏洞,但真正要执行命令、读取文件时,那些包含os、flag、__builtins__等关键词的payload几乎都会被第一时间拦截。这道题的精妙之处在于,它模拟了一个相对真实的防御环境——不仅过滤常见敏感词,还对下划线这种在Python反射中至关重要的字符进行了拦截。 本文将从实战角度出发,不局限于GHCTF2025这一道题目,而是系统性地探讨SSTI黑名单绕过的核心思路、技术原理和进阶技巧。我会结

前端通用 Token 全流程操作指南(常见常用版)

前端通用 Token 全流程操作指南(常见常用版) 本文梳理 所有前端框架通用 的 Token 操作逻辑,剥离具体项目/技术栈细节,聚焦「获取→存储→使用→过期→清除」的核心生命周期,每个步骤均标注「通用场景+通用方案+注意事项」,适合所有前端开发场景,可直接作为开发速查表。 前置说明:Token 的核心定位 Token 是后端签发的临时访问凭证,核心作用是: 1. 证明“当前用户是谁”(身份认证); 2. 证明“当前用户有权限访问”(权限校验)。 一、第一步:登录成功获取 Token 通用场景 用户通过账号密码/验证码/第三方登录等方式,向后端发起登录请求,后端验证通过后,在响应体中返回 Token。

前端图片加载失败、 img 出现裂图的原因全解析

在前端开发过程中,我们几乎都遇到过这种情况: 页面中某张图片加载不出来,显示成一个小小的“裂图”图标。 这看似简单的问题,实际上可能由多种原因造成,尤其是在 HTTPS 环境下,混合内容机制(Mixed Content) 是最常见、也最容易被误解的根源之一。 本文将带你系统梳理裂图的各种原因、排查思路,并重点讲清楚混合内容的原理与浏览器行为。 一、什么是“裂图”? “裂图”(broken image)是指浏览器尝试加载 <img> 标签的图片资源失败时的表现形式。 常见表现: * 图片区域显示为灰底、叉号、占位符; * 控制台出现 Failed to load resource 或 Mixed Content 警告; * Network 面板中图片请求状态码为 404 / 403 / blocked。 二、常见的裂图原因汇总

WebRTC / HLS / HTTP-FLV 的本质区别与选型指南

WebRTC / HLS / HTTP-FLV 的本质区别与选型指南

在做系统级直播(而不是自己本地播放)时,很多人都会遇到一个经典问题: WebRTC、HLS、HTTP-FLV 到底有什么区别? 项目中到底该选哪个? 传输协议不同 → 延迟不同 → 兼容性 / 稳定性 / 成本不同 在系统里选哪个,核心看两点: 你要多低的延迟?你要多强的兼容和稳定? 一、简介 * WebRTC:超低延迟(0.2 ~ 1s),适合实时监控、无人机、实时指挥 * HLS(hls.js):最稳、最通用(5 ~ 15s),适合活动直播、课程、公开大并发 * HTTP-FLV(flv.js):中低延迟(1 ~ 3s),适合想比 HLS 低延迟,但不想用 WebRTC 的场景(