9.2 调试排错与生产监控


9.2 调试排错与生产监控

第二道防线是可观测:开发时问题看得清、生产上问题藏不住。本节前半讲 DevTools 工具箱与水合错误定位法(第 4 章理论的实操版),后半讲生产错误捕获与上报闭环——让用户撞到的问题,在你看到报表时就已有修复在路上。

DevTools:开发期的驾驶舱

Nuxt DevTools 是官方的可视化面板,dev 模式下底部图标呼出:

// nuxt.config.ts:默认可用,显式开启确保体验完整 export default defineNuxtConfig({ devtools: { enabled: true }, })

高频用途四项:

  • 组件树检查:页面结构、嵌套布局、props 流向一目了然;
  • 状态快照:useState 与 Pinia store 的实时值,跨端状态不一致时两边对照;
  • 路由表可视化:5.1 的路由推导不用再打印到控制台;
  • 依赖与模块面板:modules 数组里每件装备的"进货档案",7.3 的评估在这里延续。

排水合错误时的定位流程(4.1 的三类成因实操化):

  1. 开发模式控制台搜 hydration mismatch 警告,读出第一个不一致的节点——后面的差异通常是连锁反应,修第一个是关键;
  2. 看该节点模板里有没有:时间显示(改成分钟粒度或水合后更新)、随机内容(挪进 onMounted)、window 判断(换 ClientOnly);
  3. 仍定位不了时二分:注释半段模板重跑,缩到具体表达式。
<template> <!-- 典型案例:评论列表的相对时间 --> <!-- 错误写法:服务端说"3 秒前",浏览器算出"4 秒前" --> <!-- <span>{{ relativeTime(comment.ts) }}</span> --> <!-- 修复:初始渲染用绝对时间(两端一致),水合后再切相对时间 --> <span>{{ hydrated ? relativeTime(comment.ts) : formatDate(comment.ts) }}</span> </template> <script setup> const hydrated = ref(false) onMounted(() => { hydrated.value = true }) // 只在浏览器翻转 </script>

生产错误捕获:三处哨位

线上没有控制台,错误要主动抓。Nuxt 的错误分三个来源,各设哨位:

哨位一:客户端运行时错误。vueApp.config.errorHandler 加 unhandledrejection 监听,插件里统一装:

// plugins/error-observer.client.ts export default defineNuxtPlugin((nuxtApp) => { nuxtApp.hook('app:error', (err) => { reportError({ kind: 'app', message: err.message, stack: err.stack }) }) window.addEventListener('unhandledrejection', (e) => { reportError({ kind: 'promise', message: String(e.reason) }) }) }) // 上报通道:发给自己第6章写的端点(同源、零依赖) function reportError(payload: Record<string, unknown>) { $fetch('/api/client-errors', { method: 'POST', body: { ...payload, url: location.href, ts: Date.now() }, }).catch(() => {}) }

哨位二:服务端错误。Nitro 的钩子兜住渲染期与接口期的异常:

// server/plugins/error-track.ts export default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook('error', (error, { event }) => { console.error('[server-error]', event?.path, error.message) // 结构化日志进收集管道(stdout 由平台日志系统接管) }) })

哨位三:用户手动的"它坏了"按钮。错误页(2.3 的 error.vue)上放反馈入口,附上错误码与页面地址——用户报告是免费的高价值样本。

上报闭环与日志纪律

捕获只是开始,闭环才是目的:

错误发生 → 哨位捕获 → 上报入库 → 聚类去重(同栈算一条) → 阈值告警(新错误/突增)→ 建议题 → 修复上线 → 曲线回落确认

自建最小方案:6.2 的 storage 或一张数据库表存错误,按"错误指纹"(栈首行哈希)聚类,每日汇总。规模上来后接专业平台(Sentry 等)——它们多提供 Nuxt 集成模块,按 7.3 的评估流程引入。

日志的工程纪律(服务端日志进不了浏览器控制台,是排查的主料):

  • 结构化:一行一条 JSON(时间、级别、路径、用户标识、耗时),别写散文日志;
  • 分级:error 必须行动、warn 值得观察、info 控制量,全级别 debug 上生产等于没有日志;
  • 脱敏:密码、token、手机号绝不进日志——日志的传播范围常比想象的大。

真实用户监控(RUM)

8.3 提过实验室测量的盲区:真实用户的设备与网络千差万别。RUM 在真实页面加载时采集三指标与接口耗时上报:

// plugins/rum.client.ts:用标准 Web API 采集,零依赖起步 export default defineNuxtPlugin(() => { onMounted(() => { // 性能时间线里的 LCP 候选 new PerformanceObserver((list) => { const entries = list.getEntries() const last = entries[entries.length - 1] report({ metric: 'lcp', value: last.startTime }) }).observe({ type: 'largest-contentful-paint', buffered: true }) }) })

采集到的分布(P75 分位是行业口径)比单次 Lighthouse 分数更接近真相:实验室九十分、真实用户 P75 四秒的站点,问题出在真实网络的某个环节(首字节慢?字体阻塞?),RUM 数据配合 8.1 的关键路径分析法收敛病因。

⚠️ 常见坑:错误上报本身抛错。上报通道故障引发新错误、新错误再触发上报,雪崩式刷量。上报函数必须自我兜底(catch 一切)并做采样与限流。

💡 关键直觉:可观测的投入产出比随用户量放大——十个用户时人肉复现还行,十万用户时"错误聚类报表 + P75 曲线"是你唯一能看见全貌的窗口。

本节要点回顾

  • DevTools 四用途:组件树、状态快照、路由可视化、模块档案;水合错误修"第一个"不一致节点;
  • 时间类水合修复模式:初始用两端一致的绝对值,onMounted 后切换动态值;
  • 三处哨位:客户端 app:error 与 unhandledrejection、Nitro 的 error 钩子、错误页反馈入口;
  • 闭环六步:捕获、上报、聚类、告警、修复、曲线确认;自建可从 6.2 storage 起步;
  • 日志三纪律:结构化、分级、脱敏;RUM 的 P75 是性能真相,实验室分数只是参考。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U