如何在 Nuxt.js 中捕获服务器错误,以免导致页面渲染崩溃? (Vue) ErrorBoundry 组件的注意事项

如何解决如何在 Nuxt.js 中捕获服务器错误,以免导致页面渲染崩溃? (Vue) ErrorBoundry 组件的注意事项

背景

这个问题与我的另一个问题 How to handle apollo client errors crashing page render in Nuxt? 相关,但我会尽量保持孤立,因为我希望这个问题只关注 Nuxt(减去 apollo)。但是,我决定单独提出这个问题,因为我正在寻找完全不同的响应/解决方案。

问题

我目前正在维护一个生产 Nuxt/Vue 应用,该应用使用 @nuxt/apollo 模块发出 GraphQL 请求。

问题在于,我们所依赖的 GraphQL 服务器时不时出现故障并返回一个 HTML 错误页面,这会导致 Apollo 客户端崩溃。但是因为我们将 Apollo 作为 nuxt 模块加载,它也会使页面渲染管道崩溃。给我们一个看起来像这样的通用服务器错误页面;

page error

服务器错误 应用程序发生错误,无法提供您的页面。如果您是应用程序所有者,请查看您的日志以了解详细信息。

以及以下堆栈跟踪:

 ERROR  Network error: Unexpected token < in JSON at position 0                                                            08:11:04

  at new ApolloError (node_modules/apollo-client/bundle.umd.js:92:26)
  at node_modules/apollo-client/bundle.umd.js:1588:34
  at node_modules/apollo-client/bundle.umd.js:2008:15
  at Set.forEach (<anonymous>)
  at node_modules/apollo-client/bundle.umd.js:2006:26
  at Map.forEach (<anonymous>)
  at QueryManager.broadcastQueries (node_modules/apollo-client/bundle.umd.js:2004:20)
  at node_modules/apollo-client/bundle.umd.js:1483:29
  at processTicksAndRejections (node:internal/process/task_queues:94:5)

然而,这些堆栈跟踪都没有让我们看到 nuxt 在哪里抛出错误,所以我们可以处理它。

我们的尝试

在过去的几周里,我们已经用尽了所有的选择来调查这个问题。我们首先尝试通过使用所有 3 个 apollo 库抽象的错误处理解决方案直接在 Apollo 级别处理错误来解决它:

  • @nuxt/apollo 模块
  • vue-apollo
  • apollo-client

如果您想阅读更多相关内容(即使它与此问题无关),您可以阅读我最初的问题 here

但是,现在我更想知道是否有办法通过以下方式处理这些页面呈现错误:

  • 使错误无声无息地失败,因此页面仍然正常呈现
  • 允许我们重定向到另一个页面。

由于我们目前使用的 apollo nuxt 模块不能用于此,我想知道 Nuxt 是否支持某种方式来处理错误。

Nuxt 的文档在错误处理方面非常有限,这并没有多大帮助。充其量,它包含有关错误页面以及如何使用 context.error 重定向到错误页面的信息。但它没有关于如何捕获常见错误的专门页面。我有一种感觉 Nuxt hooks 可能是答案,但关于它们的文档很难导航并且也很稀疏。

我在 nuxt 错误处理方面找到的最完整的信息来源是这篇文章 Error handling in NuxtJS,其中没有任何建议对我们有用。

总结

当我们使用的 @nuxt/apollo nuxt 模块崩溃时,我们的 nuxt 应用程序崩溃。我们想知道是否有某种标准的 nuxt 方法来捕获它,或者唯一可能的解决方案是将我们的整个应用程序迁移到不使用 @nuxt/apollo 模块并使用 ES6 承诺语法并加载 {{1 }} 作为一个独立的库手动进入应用程序,没有深度集成到 nuxt 生命周期中。

解决方法

编辑:我自己认为问题出在 Vue Apollo 插件或 Nuxt Apollo 模块的某个地方,以及那里的错误是如何处理的。我认为您可以直接在 Apollo 模块中处理错误,但这在 SSR 中是不可能的。

您必须记住,您可能需要针对 CSR 和 SSR 的另一种解决方案。

简而言之,发生的情况是 renderRoute 失败,因此 SSR 最终出现在 Nuxt 的默认 errorMiddleware 中。

1:直接调用 Apollo 查询,这使您可以完全控制该页面的错误处理,并且适用于 CSR 和 SSR

export default {
  mounted() {
    if (!this.books.length) {
      // client side
      this.fetchBooks()
    }
  },serverPrefetch() {
    this.fetchBooks()
  },methods: {
    fetchBooks() {
      this.$apollo
        .query({
          query: gql`
            query books {
              books {
                title
                author
                test
              }
            }
          `,})
        .catch((e) => {
          console.log(e)
        })
        .then((data) => {
          /// set books
        })
    },},}

2: 添加 errorMiddleware 钩子并处理那里的错误。这仅适用于 SSR。重要的是要了解呈现失败,因此您必须重定向或呈现另一个页面。

//nuxt.config.js
 hooks: {
    render: {
      errorMiddleware(app) {
        app.use((error,req,res,next) => {
          res.writeHead(307,{
            Location: '/network-error',})
          res.end()
        })
      },

3: Apollo的error方法返回false,只对CSR有效

export default {
  apollo: {
    books: {
      query() {
        return gql`
          query books {
            books {
              title
              author
              test
            }
          }
        `
      },error() {
        return false
      },}
,

为了防止页面崩溃,您需要处理错误并隔离它们,以免它们影响其他组件的渲染。这可以通过 ErrorBoundry 的错误处理概念来实现。您可以创建一个通用组件来重用 ErrorBoundry 逻辑。这种方法还有其他几个好处。

  • 有助于使组件不受错误处理逻辑的影响
  • 允许我们使用声明式组件组合,而不是依赖于命令式 try/catch
  • 我们可以随心所欲地使用它 — 包装单个组件或整个应用程序部分。

这是如何创建错误边界的示例。

export default {
  name: 'ErrorBoundary',data: () => ({
    error: false
  }),errorCaptured (err,vm,info) {
    this.error = true
  },render (h) {
    return this.error ? h('p','Something went wrong') : this.$slots.default[0]
  }
}

现在,您可以将任何组件包装到错误边界并按照给定的方式隔离错误,

<error-boundary>
  <counter />
</error-boundary>

ErrorBoundry 组件的注意事项

使用 errorCaptured 钩子时有一些注意事项。目前,错误仅在以下位置捕获:

  • 渲染函数
  • 观察者回调
  • 生命周期钩子
  • 组件事件处理程序

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res