5月28日 02:26

Nuxt.js 中如何处理错误和进行调试?

Nuxt.js 的错误处理和调试涉及多个层次:页面级、组件级、服务端 API 级,以及全局兜底。不同版本的 Nuxt(2 vs 3)API 差异较大,下面分别说明核心机制。

页面级错误处理

Nuxt 通过错误页面捕获路由渲染阶段的异常,给用户友好的降级体验。

Nuxt 2layouts/error.vue 中定义错误页,组件接收 error prop(含 statusCodemessage):

```vue

```

Nuxt 3 错误页改为项目根目录的 ~/error.vue(与 app.vue 同级),写法基于 Composition API:

```vue

\`\`\`

关键区别:Nuxt 3 使用 clearError() 清除错误状态,而不是自动恢复。

数据获取中的错误捕获

异步数据获取是错误高发区,Nuxt 2 和 3 的处理方式不同。

Nuxt 2asyncData 中用 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 <template #error="{ error }">

组件加载失败:{{ 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 状态码和响应体,客户端通过 useFetcherror 接收。注意不要在错误消息中拼接用户输入,避免注入风险。

全局错误钩子

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

标签:Nuxt.js