通过 100+ 个技巧学习 Nuxt!

错误处理

了解如何在 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
) => {
// 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 生命周期钩子的。

启动错误

如果启动 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 生命周期钩子。

通过在应用程序的源代码目录中,与 app.vue 并排放置 ~/error.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>
阅读更多关于 error.vue 及其用法的相关信息。

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

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 签名
function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>

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

阅读更多关于 useError 组合式函数的信息。

createError

TS 签名
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
: 'Page Not Found'
}) } </script>
阅读更多关于 createError 工具的信息。

showError

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

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

建议改为使用 throw createError()

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

clearError

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

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

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

在组件中渲染错误

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

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

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

如果你导航到另一个路由,错误将自动清除。
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>
文档 > 示例 > 高级 > 错误处理 中阅读并编辑一个实时示例。