错误处理

了解如何在 Nuxt 中捕获和处理错误。

Nuxt 是一个全栈框架,这意味着在不同的上下文中可能会发生几种无法预防的用户运行时错误:

  • 在 Vue 渲染生命周期中的错误(SSR 和 CSR)
  • 服务器和客户端启动错误(SSR + CSR)
  • 在 Nitro 服务器生命周期中的错误 (server/ 目录)
  • 下载 JS 块时的错误
SSR 代表 服务器端渲染CSR 代表 客户端渲染

Vue 错误

您可以使用 onErrorCaptured 钩子捕获 Vue 错误。

此外,Nuxt 提供了一个 vue:error 钩子,如果任何错误传播到顶层,将会被调用。

如果您使用错误报告框架,可以通过 vueApp.config.errorHandler 提供全局处理程序。即使错误被处理,它也会接收所有 Vue 错误。

plugins/error-handler.ts
export default 
defineNuxtPlugin
((
nuxtApp
) => {
nuxtApp
.
vueApp
.
config
.
errorHandler
= (
error
,
instance
,
info
) => {
// 处理错误,例如报告到服务 } // 也可以
nuxtApp
.
hook
('vue:error', (
error
,
instance
,
info
) => {
// 处理错误,例如报告到服务 }) })
请注意,vue:error 钩子是基于 onErrorCaptured 生命周期钩子的。

启动错误

如果在启动您的 Nuxt 应用程序时出现任何错误,Nuxt 将调用 app:error 钩子。

这包括:

  • 运行 Nuxt 插件
  • 处理 app:createdapp:beforeMount 钩子
  • 将您的 Vue 应用渲染为 HTML(在 SSR 期间)
  • 挂载应用(在客户端),虽然您应该使用 onErrorCapturedvue:error 钩子处理这种情况
  • 处理 app:mounted 钩子

Nitro 服务器错误

您目前无法为这些错误定义服务器端处理程序,但可以渲染错误页面,见 渲染错误页面 部分。

JS 块错误

您可能会遇到块加载错误,这可能是由于网络连接故障或新部署(导致旧的散列 JS 块 URL 无效)。Nuxt 提供内置支持来处理块加载错误,当在路由导航期间块加载失败时,它将执行硬重载。

您可以通过将 experimental.emitRouteChunkError 设置为 false(完全禁用这些错误的钩子)或设置为 manual(如果您想自行处理它们)来更改此行为。如果您想手动处理块加载错误,可以查看 自动实现 获取灵感。

错误页面

当 Nuxt 遇到致命错误(服务器上的任何未处理错误,或在客户端使用 fatal: true 创建的错误)时,它将渲染 JSON 响应(如果通过 Accept: application/json 头请求)或触发全屏错误页面。

在服务器生命周期中可能会发生错误,例如:

  • 处理您的 Nuxt 插件
  • 将您的 Vue 应用渲染为 HTML
  • 服务器 API 路由抛出错误

在客户端,错误可能发生在:

  • 处理您的 Nuxt 插件
  • 挂载应用前 (app:beforeMount 钩子)
  • 如果错误未通过 onErrorCapturedvue:error 钩子处理,则挂载应用
  • 在浏览器中初始化并挂载 Vue 应用 (app:mounted)。
了解所有 Nuxt 生命周期钩子。

通过在您的应用程序源目录中添加 ~/error.vue 来自定义默认错误页面,和 app.vue 并存。

error.vue
<script setup lang="ts">
import type { NuxtError } from '#app'

const props = defineProps({
  error: Object as () => NuxtError
})

const handleError = () => clearError({ redirect: '/' })
</script>

<template>
  <div>
    <h2>{{ error.statusCode }}</h2>
    <button @click="handleError">清除错误</button>
  </div>
</template>
阅读有关 error.vue 及其用途的更多信息。

对于自定义错误,我们强烈建议使用可以在页面/组件设置函数中调用的 onErrorCaptured 组合,或者在 Nuxt 插件中配置的 vue:error 运行时钩子。

plugins/error-handler.ts
export default 
defineNuxtPlugin
(
nuxtApp
=> {
nuxtApp
.
hook
('vue:error', (
err
) => {
// }) })

当您准备好移除错误页面时,可以调用 clearError 助手函数,该函数接受可选的重定向路径(例如,如果您想导航到一个“安全”页面)。

确保在使用任何依赖于 Nuxt 插件的内容之前进行检查,例如 $routeuseRouter,因为如果插件抛出了错误,则在清除错误之前不会重新运行。
渲染错误页面是一个完全独立的页面加载,这意味着任何已注册的中间件都会再次运行。您可以在中间件中使用 useError 检查错误是否正在被处理。
如果您在 Node 16 上运行,并且在渲染错误页面时设置了任何 cookies,它们将会 覆盖先前设置的 cookies。我们建议使用更新版本的 Node,因为 Node 16 的生命周期在 2023 年 9 月结束。

错误工具

useError

TS Signature
function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>

该函数将返回正在处理的全局 Nuxt 错误。

阅读有关 useError 组合的更多信息。

createError

TS Signature
function createError (err: string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error

创建一个带有附加元数据的错误对象。您可以传递一个字符串作为错误 message,或者一个包含错误属性的对象。它可以在应用的 Vue 和服务器部分中使用,并且旨在被抛出。

如果您抛出一个使用 createError 创建的错误:

  • 在服务器端,它将触发全屏错误页面,您可以使用 clearError 清除。
  • 在客户端,它将为您处理一个非致命错误。如果您需要触发全屏错误页面,则可以通过设置 fatal: true 来实现。
pages/movies/[slug].vue
<script setup lang="ts">
const 
route
=
useRoute
()
const {
data
} = await
useFetch
(`/api/movies/${
route
.
params
.
slug
}`)
if (!
data
.
value
) {
throw
createError
({
statusCode
: 404,
statusMessage
: '页面未找到'
}) } </script>
阅读有关 createError 工具的更多信息。

showError

TS Signature
function showError (err: string | Error | { statusCode, statusMessage }): Error

您可以在客户端的任何时刻调用此函数,或(在服务器端)直接在中间件、插件或 setup() 函数中调用。它将触发全屏错误页面,您可以使用 clearError 清除。

建议使用 throw createError() 代替。

阅读有关 showError 工具的更多信息。

clearError

TS Signature
function clearError (options?: { redirect?: string }): Promise<void>

该函数将清除当前处理的 Nuxt 错误。它还接受一个可选的重定向路径(例如,如果您想导航到一个“安全”页面)。

阅读有关 clearError 工具的更多信息。

组件中的错误渲染

Nuxt 还提供了一个 <NuxtErrorBoundary> 组件,允许您在应用内处理客户端错误,而无需用错误页面替换整个网站。

该组件用于处理其默认插槽中发生的错误。在客户端,它将防止错误向上传播并渲染 #error 插槽。

#error 插槽将接收 error 作为属性。(如果您设置 error = null,则会触发重新渲染默认插槽;您需要确保错误完全解决,否则错误插槽将再次渲染。)

如果您导航到另一个路由,错误将自动清除。
pages/index.vue
<template>
  <!-- 一些内容 -->
  <NuxtErrorBoundary @error="someErrorLogger">
    <!-- 您可以使用默认插槽渲染您的内容 -->
    <template #error="{ error, clearError }">
      您可以在这里本地显示错误:{{ error }}
      <button @click="clearError">
        这将清除错误。
      </button>
    </template>
  </NuxtErrorBoundary>
</template>
Read and edit a live example in Docs > Examples > Advanced > Error Handling.