错误处理

本文档将介绍如何处理开发阶段、服务端和客户端的错误。

开发阶段的错误处理

在 Next.js 应用的开发阶段,当出现运行时错误时,你会看到一个覆盖整个网页的错误遮罩层。该遮罩层在使用 next dev 命令(通过 pnpm devnpm run devyarn devbun dev 启动)的开发服务器运行时可见,生产环境中不会显示。修复错误后遮罩层会自动消失。

以下是错误遮罩层的示例:

开发模式下的错误遮罩层示例

服务端错误处理

Next.js 默认提供了静态 500 页面来处理应用中发生的服务端错误。你也可以通过创建 pages/500.js 文件来自定义这个页面

应用中的 500 页面不会向用户显示具体的错误信息。

你还可以使用 404 页面 来处理特定的运行时错误,例如 文件未找到

客户端错误处理

React 的 错误边界 (Error Boundaries) 是一种优雅处理客户端 JavaScript 错误的机制,可以保证应用的其他部分继续运行。除了防止页面崩溃外,它还允许你提供自定义的备用组件,甚至记录错误信息。

要在 Next.js 应用中使用错误边界,你需要创建一个类组件 ErrorBoundary,并在 pages/_app.js 文件中包裹 Component 属性。该组件将负责:

  • 在错误抛出后渲染备用 UI
  • 提供重置应用状态的方法
  • 记录错误信息

你可以通过继承 React.Component 来创建 ErrorBoundary 类组件。例如:

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props)

    // 定义状态变量来追踪是否发生错误
    this.state = { hasError: false }
  }
  static getDerivedStateFromError(error) {
    // 更新状态以便下次渲染显示备用 UI
    return { hasError: true }
  }
  componentDidCatch(error, errorInfo) {
    // 你可以在此处使用自己的错误日志服务
    console.log({ error, errorInfo })
  }
  render() {
    // 检查是否发生错误
    if (this.state.hasError) {
      // 可以渲染任何自定义备用 UI
      return (
        <div>
          <h2>糟糕,出错了!</h2>
          <button
            type="button"
            onClick={() => this.setState({ hasError: false })}
          >
            重试?
          </button>
        </div>
      )
    }

    // 没有错误时渲染子组件
    return this.props.children
  }
}

export default ErrorBoundary

ErrorBoundary 组件通过 hasError 状态变量来追踪错误。当该状态值为 true 时,组件会渲染备用 UI;否则渲染子组件。

创建好 ErrorBoundary 组件后,在 pages/_app.js 文件中导入它并包裹 Component 属性:

// 导入 ErrorBoundary 组件
import ErrorBoundary from '../components/ErrorBoundary'

function MyApp({ Component, pageProps }) {
  return (
    // 用 ErrorBoundary 组件包裹 Component 属性
    <ErrorBoundary>
      <Component {...pageProps} />
    </ErrorBoundary>
  )
}

export default MyApp

你可以在 React 文档中了解更多关于 错误边界 (Error Boundaries) 的信息。

错误上报

要监控客户端错误,可以使用 Sentry、Bugsnag 或 Datadog 等服务。

On this page