Nuxt.js 中如何处理错误和进行调试?
Nuxt.js 的错误处理和调试涉及多个层次:页面级、组件级、服务端 API 级,以及全局兜底。不同版本的 Nuxt(2 vs 3)API 差异较大,下面分别说明核心机制。
页面级错误处理
Nuxt 通过错误页面捕获路由渲染阶段的异常,给用户友好的降级体验。
Nuxt 2 在 layouts/error.vue 中定义错误页,组件接收 error prop(含 statusCode 和 message):
```vue
```
Nuxt 3 错误页改为项目根目录的 ~/error.vue(与 app.vue 同级),写法基于 Composition API:
```vue
\`\`\`关键区别:Nuxt 3 使用 clearError() 清除错误状态,而不是自动恢复。
数据获取中的错误捕获
异步数据获取是错误高发区,Nuxt 2 和 3 的处理方式不同。
Nuxt 2 在 asyncData 中用 error() 函数跳转到错误页:
```javascript export default { async asyncData({ params, $axios, error }) { try { const user = await $axios.$get(`/api/users/${params.id}`) return { user } } catch (err) { error({ statusCode: 404, message: '用户不存在' }) } } } ```
Nuxt 3 使用 useFetch / useAsyncData,通过 createError() 抛出结构化错误:
```javascript const { data, error } = await useFetch(`/api/users/${route.params.id}`) if (error.value) { throw createError({ statusCode: 404, message: '用户不存在' }) } ```
useFetch 返回的 error 是响应式引用,可以直接在模板中展示,不必跳转错误页。
组件级错误边界
Nuxt 3 提供了 <NuxtErrorBoundary> 组件,隔离组件内的客户端错误,避免整个页面崩溃:
```vue
组件加载失败:{{ error.message }}
<button @click="error = null">重试 ```适合用在仪表盘、信息流等局部模块,一个模块出错不影响其他区域。
服务端 API 错误处理
Nuxt 3 的 server routes 需要正确抛出 HTTP 错误:
```javascript // server/api/users/[id].js export default defineEventHandler(async (event) => { const id = getRouterParam(event, 'id')
const user = await db.user.findById(id) if (!user) { throw createError({ statusCode: 404, statusMessage: 'User not found' }) }
return user }) ```
服务端的 createError() 会自动设置 HTTP 状态码和响应体,客户端通过 useFetch 的 error 接收。注意不要在错误消息中拼接用户输入,避免注入风险。
全局错误钩子
Nuxt 3 提供了生命周期钩子统一捕获错误:
```javascript // plugins/error-handler.js export default defineNuxtPlugin((nuxtApp) => { nuxtApp.hook('vue:error', (error, instance, info) => { console.error('Vue error:', error, info) // 上报到 Sentry })
nuxtApp.hook('app:error', (error) => { console.error('App error:', error) }) }) ```
vue:error:Vue 组件渲染或生命周期中未捕获的错误app:error:Nuxt 初始化、插件加载等阶段的错误
配合 Sentry 或 LogRocket 可以实现错误监控和报警。
中间件中的错误处理
路由中间件里不能直接 throw,要用 abortNavigation() 中断导航:
```javascript // middleware/auth.js export default defineNuxtRouteMiddleware((to, from) => { const token = useCookie('token') if (!token.value) { return abortNavigation( createError({ statusCode: 401, message: '请先登录' }) ) } }) ```
Nuxt 2 的中间件则用 redirect() 或 error() 处理,逻辑类似但 API 不同。
调试方法
开发环境调试:
nuxt dev启动开发服务器,热重载 + source maps,直接在浏览器 DevTools 断点- Nuxt DevTools(Nuxt 3 专有):集成组件树、路由信息、payload 检查、auto-imports 可视化,通过
nuxi dev --enable-devtools开启 - Vue DevTools:查看组件 props、响应式数据、事件流
服务端调试:
```javascript // nuxt.config.ts export default defineNuxtConfig({ devServer: { debug: true } }) ```
配合 VS Code 的 Node.js 调试配置,可以给 server routes 加断点:
```json { "type": "node", "request": "launch", "name": "Nuxt Server", "program": "${workspaceFolder}/node_modules/.bin/nuxi", "args": ["dev"], "console": "integratedTerminal" } ```
构建产物分析:
```bash npx nuxi analyze ```
分析打包体积,定位过大的依赖,优化加载性能。
SSR 水合不匹配排查:
服务端渲染的 HTML 与客户端 hydration 不一致时,控制台会报 Hydration mismatch 警告。常见原因:
- 使用了
Date.now()等运行时不确定的值 - 条件渲染依赖了
window等仅客户端的对象 - 解决方案:用
<ClientOnly>包裹客户端专属内容,或用onMounted延迟赋值
常见问题
chunk 加载失败:新部署后旧页面的 JS chunk URL 失效,Nuxt 3 会自动硬重载;Nuxt 2 需手动监听 window.onerror 中的 chunk 错误并刷新。
500 错误定位:优先检查 server routes 的 try-catch 是否遗漏,用 console.error 打印完整堆栈,确认 API 调用参数和返回格式。
asyncData 报错但页面空白:Nuxt 2 中 asyncData 未调用 error() 时,错误会被静默吞掉。确保 catch 块中调用 error() 或至少 console.error。