如何在 Nuxt.js 中捕获服务器错误,以免导致页面渲染崩溃?(Vue)

sga*_*dev 7 javascript apollo vue.js nuxt.js

语境

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

问题

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

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

页面错误

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

以及以下堆栈跟踪:

 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)
Run Code Online (Sandbox Code Playgroud)

然而,这些堆栈跟踪都不允许我们看到 nuxt 在哪里抛出错误,因此我们可以处理它。

我们尝试过的

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

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

如果您想阅读更多相关内容(即使它与此问题无关),您可以在此处阅读有关我的原始问题的更多信息

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

  • 使错误以静默方式失败,因此页面仍然正常呈现
  • 允许我们重定向到另一个页面。

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

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

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

概括

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

Vic*_*rez 6

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

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

简而言之,发生的情况是失败renderRoute,并且由于此 SSR 最终成为errorMiddlewareNuxt 的默认值。

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
        })
    },
  },
}
Run Code Online (Sandbox Code Playgroud)

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

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

Run Code Online (Sandbox Code Playgroud)

3: Apollo方法中返回false error,这只适用于CSR

export default {
  apollo: {
    books: {
      query() {
        return gql`
          query books {
            books {
              title
              author
              test
            }
          }
        `
      },
      error() {
        return false
      },
    },
  },
}
Run Code Online (Sandbox Code Playgroud)