页面的异常处理
在服务端渲染中,页面预渲染需要的数据一般由服务器提供。在 Next.js 框架中,可分为两种。Next.js 作为全站框架,获取数据直接在 Next.js 服务中调用方法;或者借助外部 API 服务,通过 HTTP 或者其他方式获取数据。
在获取数据的过程中,可能会出现异常,例如网络请求超时、服务端异常等。这时候,我们需要对异常进行处理,以保证页面的正常渲染。
编写一个简单的数据接口和页面渲染
下面是一个简单的例子。这是一个简单的获取 posts
接口实现。
上面的例子中我们模拟了几种情况:
- 当请求
posts/1
时,返回正常数据 - 当请求
posts/2
时,返回 403 错误 - 当请求其他路径时,返回 404 错误
然后我们来编写一个简单的数据渲染页面。
现在我们来访问 posts/1
,可以看到页面正常渲染。
页面错误兜底页
在 App Router 中,我们可以编写 error.jsx
和 global-error.jsx
去处理服务端渲染中的异常,当页面渲染异常,那么会回退到错误页面。
对于 error.jsx
和 global-error.jsx
的区别:
- 前者是对于每个 Page 或者 Layout 中发生的错误处理。这个错误是局部的,所以在错误组件的上层仍然存在其他组件。
- 后者是全局的错误处理,当渲染 Root Layout 中发生错误时,此时会回退到全局错误处理页面。
发生错误时,如果当前的 Route Segment 不存在 error.jsx
,那么会向上查找。
Note
global-error.jsx
无法处理所有的 Next.js 渲染页面中发生的异常。例如 Next.js 在 Middleware 中发生异常,此时我们会得到 Next.js 直接抛出的异常页,500 | Internal Server Error
。
编写一个简单的 error.jsx
页面。
Error Page 必须是一个 Client Component,并且他可以接受一个 error
props,但是这个 error
prop 的 message
是被处理过的,我们无法根据这个 error 去判断任何页面渲染逻辑,比如当 Error 为 RequestError 时根据 HTTP Code 去渲染不同的 UI。
error
prop 的 Error 对象,存在两个属性:
message
: 在生产环境中,error
的 message 一般都是Server Component error
,这个信息对于 UI 渲染来说是没有意义的。digest
: 可以方便开发者在生产环境中快速定位异常。
现在我们来访问 posts/2
,可以看到页面渲染了错误页面。
404 处理
404 处理是最常见的异常,例如当我们访问一篇不存在的文章时,我们需要渲染 404 页面,此时预渲染页面请求的数据接口是异常的。我们需要根据这个异常去让 Next.js 应用触发 NOT_FOUND
的逻辑。
再之前的例子中,我们直接访问 posts/3
,这个路径是不存在的,我们可以看到请求报错了,页面回退到了我们定义的 error.jsx
。
但是因为在 error.jsx
中,我们已经拿不到原始的 Error 对象,所以在 error.jsx
中无法判断是 404 错误还是其他错误。
在 App Router 架构中,我们可以使用 notFound()
方法,强制跳转到 404 页面,此时页面的 HTTP 状态为 404
。
此时再次访问 posts/3
,可以看到页面已经跳转到 404 页面。
这是 Next.js 默认的 404 页面,我们也可以编写一个自定义的 404 页面。
not-found.jsx
和 error.jsx
一样,如果发生错误的 Route Segment 层级不存在定义时,会逐级向上查找。
其他异常处理
在请求中或许还会出现其他的异常,而最常见的还是请求异常。比如 403 异常,或者服务器异常导致 500 等等。
因为 Next.js
并没有提供这类异常的处理方法,所以根据这些情况我们需要手动判断去渲染不同 UI。
这样虽然达成了目的,但是这样的代码显得有些冗余,我们可以通过封装一个函数来简化这个逻辑。
使用方法为:
因为在 definePrerenderPage
中,我们已经处理对 RequestError 的各种情况做了 UI 的处理,所以这里我们不需要在手写这些逻辑,而是更加关注业务本身。
需要注意的是,RequestError 这里需要借助请求库的 onRequestError 等钩子去抛出,这样我们才能在异常时判断出是请求的异常,然后再做相应的处理。
上面的 Demo 位于:nextjs-book/tree/main/demo/page-error-handle
最后更新于 2024/7/26 16:15:59
本书还在编写中..
前往 https://innei.in/posts/tech/my-first-nextjs-book-here#comment 发表你的观点吧。