错误处理
学习如何在 Nuxt 中捕获和处理错误。
Nuxt 是一个全栈框架,这意味着在不同的上下文中可能会发生多种无法预防的用户运行时错误:
- Vue 渲染生命周期中的错误(SSR & CSR)
- 服务器和客户端启动错误(SSR + CSR)
- Nitro 服务器生命周期中的错误(
server/
目录) - 下载 JS 块时的错误
SSR 代表 服务器端渲染,CSR 代表 客户端渲染。
Vue 错误
您可以使用 onErrorCaptured
钩子捕获 Vue 错误。
此外,Nuxt 提供了一个 vue:error
钩子,如果任何错误传播到顶层时将被调用。
如果您使用错误报告框架,可以通过 vueApp.config.errorHandler
提供一个全局处理程序。它将接收所有 Vue 错误,即使它们已被处理。
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:created
和app:beforeMount
钩子 - 将您的 Vue 应用渲染为 HTML(在 SSR 期间)
- 挂载应用程序(在客户端),尽管您应该使用
onErrorCaptured
或vue: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
钩子) - 如果错误未通过
onErrorCaptured
或vue:error
钩子处理,则挂载您的应用 - Vue 应用在浏览器中初始化并挂载(
app:mounted
)。
通过在应用程序的源目录中添加 ~/error.vue
来自定义默认错误页面,与 app.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>
对于自定义错误,我们强烈建议使用 onErrorCaptured
组合函数,可以在页面/组件设置函数中调用,或在 Nuxt 插件中配置的 vue:error
运行时 Nuxt 钩子。
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.hook('vue:error', (err) => {
//
})
})
当您准备好移除错误页面时,可以调用 clearError
辅助函数,该函数接受一个可选的重定向路径(例如,如果您想导航到一个“安全”页面)。
确保在使用任何依赖于 Nuxt 插件的内容之前进行检查,例如 $route
或 useRouter
,因为如果插件抛出错误,则在您清除错误之前不会重新运行。
渲染错误页面是一个完全独立的页面加载,这意味着任何注册的中间件将再次运行。您可以在中间件中使用 useError
来检查是否正在处理错误。
如果您在 Node 16 上运行并在渲染错误页面时设置了任何 cookie,它们将 覆盖之前设置的 cookie。我们建议使用更新版本的 Node,因为 Node 16 在 2023 年 9 月已达到生命周期终点。
错误工具
useError
function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>
此函数将返回正在处理的全局 Nuxt 错误。
另请参阅 api > composables > use-errorcreateError
function createError (err: string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error
创建一个带有附加元数据的错误对象。您可以传递一个字符串作为错误 message
,或包含错误属性的对象。它可以在应用程序的 Vue 和服务器部分使用,并且旨在被抛出。
如果您抛出一个使用 createError
创建的错误:
- 在服务器端,它将触发一个全屏错误页面,您可以使用
clearError
清除。 - 在客户端,它将抛出一个非致命错误供您处理。如果您需要触发全屏错误页面,可以通过设置
fatal: true
来实现。
const route = useRoute()
const { data } = await useFetch(`/api/movies/${route.params.slug}`)
if (!data.value) {
throw createError({
statusCode: 404,
statusMessage: '页面未找到'
})
}
showError
function showError (err: string | Error | { statusCode, statusMessage }): Error
您可以在客户端的任何时候调用此函数,或(在服务器端)直接在中间件、插件或 setup()
函数中调用。它将触发一个全屏错误页面,您可以使用 clearError
清除。
建议使用 throw createError()
。
clearError
function clearError (options?: { redirect?: string }): Promise<void>
此函数将清除当前处理的 Nuxt 错误。它还接受一个可选的重定向路径(例如,如果您想导航到一个“安全”页面)。
另请参阅 api > utils > clear-error在组件中渲染错误
Nuxt 还提供了一个 <NuxtErrorBoundary>
组件,允许您在应用程序中处理客户端错误,而无需用错误页面替换整个站点。
此组件负责处理在其默认插槽中发生的错误。在客户端,它将防止错误冒泡到顶层,并将渲染 #error
插槽。
#error
插槽将接收 error
作为 prop。(如果您设置 error = null
,它将触发重新渲染默认插槽;您需要确保错误已完全解决,否则错误插槽将再次被渲染。)
如果您导航到另一个路由,错误将自动清除。
<template>
<!-- 一些内容 -->
<NuxtErrorBoundary @error="someErrorLogger">
<!-- 您可以使用默认插槽渲染您的内容 -->
<template #error="{ error, clearError }">
您可以在此处本地显示错误:{{ error }}
<button @click="clearError">
这将清除错误。
</button>
</template>
</NuxtErrorBoundary>
</template>