如何在NuxtJS SSR中全局捕获处理VueJS的500错误
NuxtJS SSR 全局捕获处理500错误实现方案
Nuxt 本身提供了多层原生的全局错误处理机制,可完整覆盖SSR运行全流程的500类错误,支持通过插件、钩子、自定义中间件等方式实现错误记录、统一兜底逻辑,不需要从零改造底层渲染逻辑,具体实现方案按覆盖场景分类如下:
1. 全局错误兜底页(全场景通用)
在项目根目录(与app.vue、pages目录同级)新建error.vue文件,该文件会自动接管服务端、客户端抛出的所有错误(包含500、404等各类状态码错误),是官方推荐的全局错误兜底入口:
<template> <div class="error-container"> <h2>请求出错 {{ error.statusCode }}</h2> <p v-if="error.statusCode === 500">服务端暂时不可用,请稍后重试</p> <button @click="goHome">返回首页</button> </div> </template> <script setup> const props = defineProps({ error: Object }) const router = useRouter() // 错误触发时自动执行记录/上报逻辑 onMounted(() => { if (props.error.statusCode === 500) { // 此处可添加错误上报、日志落盘逻辑,可获取错误栈、请求路径、用户标识等上下文 console.error('捕获到500错误:', props.error) } }) const goHome = () => router.push('/') </script>
注意:error.vue同时生效于服务端渲染阶段和客户端激活阶段,SSR阶段抛出的500错误也会完整传入该组件。
2. 服务端前置错误钩子(SSR阶段专属)
如果需要在响应返回给客户端之前就捕获SSR流程的500错误,做无感知的日志记录,可通过Nitro服务端插件注册全局错误钩子,执行时机早于错误页渲染:
在server/plugins/目录下新建error-log.ts:
export default defineNitroPlugin((nitroApp) => { nitroApp.hooks.hook('error', (error, { event }) => { if (event.node.res.statusCode === 500) { // 此处可记录服务端错误日志、上报监控系统 console.error(`SSR 500错误,请求路径:${event.node.req.url}`, error) } }) })
3. 客户端运行时错误捕获
针对客户端水合、组件运行、异步请求抛出的500类错误,可注册客户端专属插件做全局监听:
在plugins/目录下新建client-error.client.ts(后缀.client.ts表示仅在客户端加载):
export default defineNuxtPlugin((nuxtApp) => { // 捕获Vue组件运行时错误 nuxtApp.vueApp.config.errorHandler = (error, instance, info) => { console.error('客户端Vue运行时错误:', error, info) // 错误上报逻辑 } // 捕获全局未处理的JS错误 window.addEventListener('error', (event) => { console.error('客户端全局JS错误:', event.error) }) // 捕获未处理的Promise异步错误 window.addEventListener('unhandledrejection', (event) => { console.error('客户端未捕获异步错误:', event.reason) }) })
4. 自定义中间件拦截方案
如果需要在路由、接口请求层面对500错误做前置拦截,也可以通过自定义中间件实现:
- 路由中间件:在
middleware/目录下新建全局路由中间件,可捕获路由跳转、中间件执行过程中抛出的500错误,但覆盖范围小于上述官方钩子方案 - 请求统一拦截:如果项目统一使用
$fetch/useFetch做接口请求,可封装统一请求实例,在响应拦截层统一处理接口返回的500状态码:
// 封装统一请求实例 const request = $fetch.create({ onResponseError({ response }) { if (response.status === 500) { console.error('接口返回500错误:', response._data) // 统一错误提示、上报逻辑 } } })
问题参考错误截图


内容的提问来源于stack exchange,提问作者Finn
相关产品推荐
相关产品推荐

