错误处理

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

Nuxt 是一个全栈框架,这意味着在不同情况下,用户运行时可能会遇到多种不可预防的错误:

¥Nuxt is a full-stack framework, which means there are several sources of unpreventable user runtime errors that can happen in different contexts:

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

Vue 错误

¥Vue Errors

你可以使用 onErrorCaptured 钩住 Vue 错误。

¥You can hook into Vue errors using onErrorCaptured.

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

¥In addition, Nuxt provides a vue:error hook that will be called if any errors propagate up to the top level.

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

¥If you are using an error reporting framework, you can provide a global handler through vueApp.config.errorHandler. It will receive all Vue errors, even if they are handled.

plugins/error-handler.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
    // handle error, e.g. report to a service
  }

  // Also possible
  nuxtApp.hook('vue:error', (error, instance, info) => {
    // handle error, e.g. report to a service
  })
})
请注意,vue:error 钩子基于 onErrorCaptured 生命周期钩子。

启动错误

¥Startup Errors

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

¥Nuxt will call the app:error hook if there are any errors in starting your Nuxt application.

这包括:

¥This includes:

  • 运行 Nuxt 插件
  • 处理 app:createdapp:beforeMount 钩子
  • 将你的 Vue 应用渲染为 HTML(在服务器端渲染期间)
  • 在客户端挂载应用,但你应该使用 onErrorCapturedvue:error 来处理这种情况。
  • 处理 app:mounted 钩子

Nitro 服务器错误

¥Nitro Server Errors

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

¥You cannot currently define a server-side handler for these errors, but can render an error page, see the Render an Error Page section.

JS 代码块错误

¥Errors with JS Chunks

你可能会因为网络连接故障或新部署(这会使旧的、经过哈希处理的 JS 块 URL 失效)而遇到块加载错误。Nuxt 内置了处理块加载错误的支持,当路由导航期间块加载失败时,会执行硬重新加载。

¥You might encounter chunk loading errors due to a network connectivity failure or a new deployment (which invalidates your old, hashed JS chunk URLs). Nuxt provides built-in support for handling chunk loading errors by performing a hard reload when a chunk fails to load during route navigation.

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

¥You can change this behavior by setting experimental.emitRouteChunkError to false (to disable hooking into these errors at all) or to manual if you want to handle them yourself. If you want to handle chunk loading errors manually, you can check out the the automatic implementation for ideas.

错误页面

¥Error Page

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

在服务器生命周期中,以下情况可能会发生错误:

¥An error may occur during the server lifecycle when:

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

在以下情况下,它也可以在客户端发生:

¥It can also occur on the client side when:

  • 处理你的 Nuxt 插件
  • 在挂载应用之前(app:beforeMount 钩子)
  • 如果错误未通过 onErrorCapturedvue:error 钩子处理,则挂载你的应用。
  • Vue 应用在浏览器(app:mounted)中初始化并挂载。

:

Read more in Docs > API > Advanced > Hooks.

探索所有 Nuxt 生命周期钩子。

¥Discover all the Nuxt lifecycle hooks.

::

通过在应用的源目录中添加 ~/error.vueapp.vue 来自定义默认错误页面。

¥Customize the default error page by adding ~/error.vue in the source directory of your application, alongside 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">Clear errors</button>
  </div>
</template>

:

Read more in Docs > Guide > Directory Structure > Error.

阅读更多关于 error.vue 及其用途的内容。

¥Read more about error.vue and its uses.

::

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

¥For custom errors we highly recommend to use onErrorCaptured composable that can be called in a page/component setup function or vue:error runtime nuxt hook that can be configured in a nuxt plugin.

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

当你准备移除错误页面时,可以调用 clearError 辅助函数,该函数接受一个可选的重定向路径(例如,如果你想导航到 'safe' 页面)。

¥When you are ready to remove the error page, you can call the clearError helper function, which takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page).

在使用任何依赖于 Nuxt 插件(例如 $routeuseRouter)之前,请务必进行检查,因为如果插件抛出错误,则在清除错误之前不会重新运行。
渲染错误页面是完全独立的页面加载,这意味着任何已注册的中间件都将再次运行。你可以在中间件中使用 useError 来检查错误是否正在被处理。
如果你在 Node 16 上运行,并且在渲染错误页面时设置了任何 Cookie,它们都会被 overwrite cookies previously set 覆盖。我们建议你使用较新版本的 Node,因为 Node 16 已于 2023 年 9 月停止支持。

错误工具

¥Error Utils

useError

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

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

¥This function will return the global Nuxt error that is being handled.

:

Read more in Docs > API > Composables > Use Error.

阅读更多关于 useError 可组合项的内容。

¥Read more about useError composable.

::

createError

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

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

¥Create an error object with additional metadata. You can pass a string to be set as the error message or an object containing error properties. It is usable in both the Vue and Server portions of your app, and is meant to be thrown.

如果你在使用 createError 创建时抛出错误:

¥If you throw an error created with 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: 'Page Not Found'
  })
}
</script>

:

Read more in Docs > API > Utils > Create Error.

阅读更多关于 createError 实用程序的内容。

¥Read more about createError util.

::

showError

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

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

¥You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or setup() functions. It will trigger a full-screen error page which you can clear with clearError.

建议使用 throw createError()

¥It is recommended instead to use throw createError().

:

Read more in Docs > API > Utils > Show Error.

阅读更多关于 showError 实用程序的内容。

¥Read more about showError util.

::

clearError

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

此函数将清除当前处理的 Nuxt 错误。它还接受一个可选的重定向路径(例如,如果你想导航到 'safe' 页面)。

¥This function will clear the currently handled Nuxt error. It also takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page).

:

Read more in Docs > API > Utils > Clear Error.

阅读更多关于 clearError 实用程序的内容。

¥Read more about clearError util.

::

组件渲染错误

¥Render Error in Component

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

¥Nuxt also provides a <NuxtErrorBoundary> component that allows you to handle client-side errors within your app, without replacing your entire site with an error page.

此组件负责处理其默认插槽中发生的错误。在客户端,它将阻止错误冒泡到顶层,而是渲染 #error 插槽。

¥This component is responsible for handling errors that occur within its default slot. On client-side, it will prevent the error from bubbling up to the top level, and will render the #error slot instead.

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

¥The #error slot will receive error as a prop. (If you set error = null it will trigger re-rendering the default slot; you'll need to ensure that the error is fully resolved first or the error slot will just be rendered a second time.)

如果你导航到其他路由,错误将自动清除。
pages/index.vue
<template>
  <!-- some content -->
  <NuxtErrorBoundary @error="someErrorLogger">
    <!-- You use the default slot to render your content -->
    <template #error="{ error, clearError }">
      You can display the error locally here: {{ error }}
      <button @click="clearError">
        This will clear the error.
      </button>
    </template>
  </NuxtErrorBoundary>
</template>
Read and edit a live example in Docs > Examples > Advanced > Error Handling.