一、错误监控与上报
1. 错误类型覆盖
| 错误类型 | 捕获方式 |
|---|
| JS 运行时错误 | window.onerror / window.addEventListener('error') |
| Promise 未捕获异常 | window.addEventListener('unhandledrejection') |
| 资源加载失败 | window.addEventListener('error', e => e.target.src, true) 捕获阶段 |
| 框架内部错误 | Vue errorHandler、React ErrorBoundary |
| 接口请求失败 | axios 拦截器 / fetch wrapper 统一捕获 |
| 跨域脚本错误 | 服务端添加 Access-Control-Allow-Origin,script 标签加 crossorigin |
2. 错误信息收集要素
- 错误信息:message、stack trace
- 用户环境:浏览器、OS、设备、网络类型
- 页面信息:URL、路由、referrer
- 用户行为:操作路径(breadcrumbs)、用户 ID
- 业务上下文:版本号、实验组、关键业务参数
3. Source Map 还原
- 生产环境代码压缩后,需上传 Source Map 到监控平台
- 构建时自动上传(Sentry webpack plugin / vite plugin)
- Source Map 文件不对外暴露,只在监控后台还原堆栈
4. 采样与聚合
- 采样上报:高流量场景按比例采样,避免上报风暴
- 错误聚合:相同 stack 的错误合并计数,关注影响用户数而非绝对次数
- 告警阈值:错误率(错误 PV / 总 PV)超过阈值触发告警
二、异常处理与降级
1. 全局兜底
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
componentDidCatch(error, info) { reportError(error, info); }
render() {
return this.state.hasError ? <FallbackUI /> : this.props.children;
}
}
app.config.errorHandler = (err, instance, info) => {
reportError(err, { info });
};
2. 接口异常处理
- 统一错误拦截:在请求层统一处理 HTTP 错误码,避免散落各处
- 接口降级:接口失败时展示缓存数据或默认值,而非白屏
- 超时处理:设置合理的请求超时(建议 10s),超时给用户明确提示
- 重试机制:幂等接口失败后自动重试(指数退避),避免雪崩
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await fetch(url);
} catch (e) {
if (i === retries - 1) throw e;
await sleep(2 ** i * 1000);
}
}
}
3. 渲染降级策略
- 组件级降级:局部组件报错不影响整体页面
- 功能降级:非核心功能(推荐、广告)失败时静默隐藏
- 离线降级:Service Worker 缓存兜底,弱网/断网仍可访问核心页面
三、发布与版本管理
1. 灰度发布
- 按用户比例(1% → 10% → 100%)逐步放量
- 按用户标签(内部员工 → 白名单用户 → 全量)
- 发布后观察错误率、核心指标,异常立即回滚
2. 功能开关(Feature Flag)
- 新功能上线前用开关控制,出问题直接关闭,无需重新发布
- 支持远程配置(LaunchDarkly、自研配置中心)
- A/B 实验、灰度、降级三合一管理
3. 回滚机制
- 构建产物保留历史版本(至少保留最近 10 个)
- CDN 支持一键回滚到上一版本
- 发布流程内置自动回滚:核心指标下降超阈值自动触发
4. 版本兼容
- 前后端接口变更遵循向后兼容原则,字段废弃而非删除
- 长缓存资源文件名带 hash,避免用户拿到旧 JS + 新接口的错误组合
- 发布期间处理新旧版本并存问题(页面切换检测到新版本提示刷新)
四、代码质量保障
1. 静态检查
- ESLint:代码规范、潜在 bug 检测
- TypeScript:类型系统,消灭一类运行时错误
- Prettier:统一代码风格,减少低级差异
- Husky + lint-staged:提交前自动 lint,拦截问题代码入库
2. 测试体系
| 测试类型 | 工具 | 覆盖目标 |
|---|
| 单元测试 | Vitest / Jest | 工具函数、hooks、核心逻辑 |
| 组件测试 | Testing Library | 组件渲染、交互行为 |
| E2E 测试 | Playwright / Cypress | 核心用户流程(登录、下单等) |
| 视觉回归 | Storybook + Chromatic | UI 样式变化检测 |
- 覆盖率要求:核心业务逻辑覆盖率建议 ≥ 80%
- CI 门禁:测试不通过禁止合并 PR
3. Code Review 重点
- 边界条件处理(空值、异常流)
- 异步错误是否有 catch
- 依赖版本是否锁定(
package-lock.json / yarn.lock 入库)
五、依赖管理
1. 依赖安全
- 定期审计:
npm audit 扫描已知漏洞
- Dependabot / Renovate:自动提 PR 更新依赖,配合测试验证
- 锁定版本:生产依赖锁定具体版本,避免小版本 breaking change
2. 依赖治理
- 评估引入新依赖的必要性(体积、维护状态、安全记录)
- 避免依赖废弃/不维护的库
- 核心依赖有替代方案预案(如某 CDN 挂了的 fallback)
六、前端容灾
1. 静态资源容灾
- 多 CDN 备援:主 CDN 故障时自动切换备用 CDN
- 资源完整性校验:
<script integrity="sha256-..."> 防止 CDN 投毒
- 本地兜底:关键 SDK(埋点、监控)在 CDN 失败时从自有域名加载
<script
src="https://cdn.example.com/lib.js"
integrity="sha256-xxxx"
crossorigin="anonymous"
onerror="loadFallback()"
></script>
2. 弱网与断网处理
- 网络状态检测:监听
online / offline 事件,给用户提示
- 请求队列:断网期间的写操作排队,网络恢复后自动重发
- Service Worker 离线缓存:核心页面和静态资源离线可访问
3. 第三方依赖隔离
- 第三方脚本(广告、统计)异常不能影响主业务
- 用
try/catch 包裹第三方调用
- 通过
iframe 或 Web Worker 隔离高风险第三方代码
七、监控告警体系
1. 监控指标分层
业务指标(最终目标)
├── 转化率、下单成功率、支付成功率
↑ 由以下支撑
前端质量指标
├── JS 错误率(错误 PV / 总 PV)
├── 接口成功率
├── 页面白屏率
└── 核心 Web Vitals(LCP、INP、CLS)
2. 告警分级
| 级别 | 触发条件示例 | 响应要求 |
|---|
| P0 紧急 | 错误率 > 5%,核心页面白屏 | 立即响应,15min 内处理 |
| P1 重要 | 错误率 > 1%,核心接口失败率上升 | 30min 内响应 |
| P2 一般 | 错误率小幅上升,非核心功能异常 | 工作时间内处理 |
3. 常用监控平台
- Sentry:错误监控首选,Source Map 还原、issue 聚合
- Datadog / 阿里云 ARMS:全链路 APM,前后端关联分析
- 自研上报 + Grafana:灵活定制,适合大团队
八、稳定性文化与流程
- 变更管理:上线前填写变更单,明确影响范围和回滚方案
- 故障复盘:每次 P0/P1 事故必须复盘,输出改进 Action
- 混沌工程:主动注入故障(断网、接口超时),验证降级方案有效性
- 值班制度:生产环境告警有人 oncall,响应 SLA 明确
- 上线时间窗口:避免周五下班前、节假日前发布高风险变更
九、稳定性建设优先级
基础保障(必须做)
├── 全局错误捕获 + 上报
├── 接口统一异常处理与超时
├── ErrorBoundary / Vue errorHandler
├── ESLint + TypeScript
└── 灰度发布 + 快速回滚
进阶治理
├── Source Map 还原
├── Feature Flag 功能开关
├── 核心流程 E2E 测试
└── 多 CDN 备援
高阶完善
├── 混沌工程
├── 全链路 APM
└── 弱网/离线 Service Worker
稳定性的本质:快速发现问题 → 快速定位问题 → 快速恢复服务 → 防止问题复发。