错误处理
Nuxt 是一个全栈框架,这意味着在不同的上下文中可能会发生几个无法预防的用户运行时错误:
- Vue 渲染生命周期中的错误(SSR & CSR)
- 服务器和客户端启动错误(SSR + CSR)
- Nitro 服务器生命周期中的错误(
server/目录) - 下载 JS chunk 时的错误
Vue 错误
您可以使用 onErrorCaptured 钩子捕获 Vue 错误。
此外,如果任何错误传播到顶层,Nuxt 会提供一个 vue:error 钩子将被调用。
如果您正在使用错误报告框架,您可以通过 vueApp.config.errorHandler 提供一个全局处理程序。它将接收所有 Vue 错误,即使这些错误已被处理。
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:created和app:beforeMount钩子 - 将您的 Vue 应用程序渲染为 HTML(在 SSR 期间)
- 挂载应用程序(在客户端),尽管您应该使用
onErrorCaptured或vue:error处理这种情况 - 处理
app:mounted钩子
Nitro 服务器错误
您目前无法为这些错误定义服务器端处理程序,但可以渲染错误页面,请参阅 渲染错误页面 部分。
JS Chunk 错误
由于网络连接失败或新的部署(这会使您旧的、哈希化的 JS chunk URL 无效),您可能会遇到 chunk 加载错误。Nuxt 提供了内置的支持来处理 chunk 加载错误,方法是在路由导航期间 chunk 加载失败时执行硬重新加载。
您可以通过将 experimental.emitRouteChunkError 设置为 false(完全禁用对这些错误的挂钩)或设置为 manual(如果您想自己处理它们)来更改此行为。如果您想手动处理 chunk 加载错误,您可以查看 自动实现 以获取灵感。
错误页面
fatal: true 创建的错误)时,它将渲染 JSON 响应(如果请求带有 Accept: application/json header)或触发全屏错误页面。在服务器生命周期中可能会发生错误,当:
- 处理您的 Nuxt 插件时
- 将您的 Vue 应用程序渲染为 HTML 时
- 服务器 API 路由抛出错误时
- 在客户端也可能发生错误,当:
- 处理您的 Nuxt 插件时
- 在挂载应用程序之前(
app:beforeMount钩子) - 如果错误没有被
onErrorCaptured或vue:error钩子处理,则在挂载您的应用程序时 - Vue 应用程序在浏览器中初始化和挂载时 (
app:mounted)。
通过在应用程序的源目录(与 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>
对于自定义错误,我们强烈建议使用可以在页面/组件 setup 函数中调用的 onErrorCaptured composable,或者可以在 nuxt 插件中配置的 vue:error 运行时 nuxt 钩子。
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.hook('vue:error', (err) => {
//
})
})
当您准备删除错误页面时,您可以调用 clearError 辅助函数,该函数接受一个可选的重定向路径(例如,如果您想导航到 “安全” 页面)。
请务必在使用任何依赖 Nuxt 插件的内容(例如 $route 或 useRouter)之前进行检查,因为如果某个插件抛出错误,那么在您清除错误之前它不会重新运行。
useError 来检查是否正在处理错误。错误工具
useError
function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>
此函数将返回当前正在处理的全局 Nuxt 错误。
createError
function createError (err: string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error
创建一个包含附加元数据的错误对象。您可以传递一个字符串作为错误 message,也可以传递一个包含错误属性的对象。它在应用程序的 Vue 和 Server 部分都可用,并且旨在被抛出。
如果您抛出一个使用 createError 创建的错误:
- 在服务器端,它将触发一个全屏错误页面,您可以使用
clearError清除该页面。 - 在客户端,它将抛出一个非致命错误供您处理。如果您需要触发全屏错误页面,则可以通过设置
fatal: true来实现。
<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>
showError
function showError (err: string | Error | { statusCode, statusMessage }): Error
您可以在客户端的任何时候调用此函数,也可以(在服务器端)直接在中间件、插件或 setup() 函数中调用。它将触发一个全屏错误页面,您可以使用 clearError 清除该页面。
建议改为使用 throw createError()。
clearError
function clearError (options?: { redirect?: string }): Promise<void>
此函数将清除当前处理的 Nuxt 错误。它还接受一个可选的重定向路径(例如,如果您想导航到 “安全” 页面)。
在组件中渲染错误
Nuxt 还提供了一个 <NuxtErrorBoundary> 组件,允许您在应用程序中处理客户端错误,而无需用错误页面替换整个站点。
此组件负责处理其默认插槽中发生的错误。在客户端,它将阻止错误冒泡到顶层,并改为渲染 #error 插槽。
#error 插槽将接收 error 作为 prop。(如果您设置 error = null,它将触发重新渲染默认插槽;您需要确保首先完全解决错误,否则错误插槽只会再次渲染。)
<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>