NuxtJS 错误处理

3,970 阅读3分钟

简介

NuxtJS中的错误从产生到流经到最后的展示,有着一套既定的规则。本文通过对NuxtJS框架中错误流转的介绍,帮助读者准确的定位错误,并正确处理应用中的错误。

通过本文,你可以:

  1. 了解NuxtJS错误的分类与流转机制
  2. 了解不同错误的捕获方式与处理技巧
  3. 了解NuxtJS错误页的展示原理,以及自定义错误页。

错误来源

NuxtJS框架中的错误来源有以下三种:

  1. 事件处理函数
  2. asyncData方法
  3. 组件模版渲染

错误产生及传播可由下面的两张图表示:

【图1】事件处理函数中抛出的错误仅会出现在客户端(client-side) 【图1】事件处理函数中抛出的错误仅会出现在客户端(client-side)

image.png 【图2】asyncData方法中以及组件模版渲染中抛出的错误既可能出现在客户端(client-side)也可能出现在服务端(server-side)

错误处理

抛出的错误可以在以下四个位置进行捕获:

  1. errorCapture
  2. Vue.js errorHandler
  3. onunhandledrejection
  4. render:errorMiddleware

errorCapture

errorCapture是Vue组件的一个生命周期Hook,在NuxtJS中,同样可以为Layout组件添加。在Layout组件中设置errorCapture,可以让你全局捕获和处理这些错误:

  1. 事件处理函数(client-side)中的同步错误
  2. 组件模版渲染(client-side & server-side)中的错误

DEMO in 默认Layout - NuxtJS

/**
 * @file layouts/default.vue
 */

import Vue from 'vue'
import Component from 'vue-class-component'

@Component({
  errorCaptured(err, vm, info) {
    if (info === 'render') {
      console.log('这是一个组件渲染的错误')
    } else {
      console.log('这是一个事件处理的错误')
    }

    console.log('[errorCaptured 错误处理]: ', err, vm, info)

    // 阻止错误继续向外传播
    return false
  },
})
export default class Layout extends Vue {
  ...
}

errorHandler

errorHandler 是Vue全局配置的一项,你可以使用它去捕获和处理这些错误:

  1. 事件处理函数(client-side)中的同步错误且未被errorCapture处理掉
  2. 组件模版渲染(client-side)的错误且未被errorCapture处理掉

DEMO in plugins - NuxtJS

/**
 * @file plugins/monitor.client.js
 */
import Vue from 'vue'

export default function (ctx) {
  Vue.config.errorHandler = (error, vm, info) => {
    console.log('[errorHandler 错误处理]: ', err, vm, info)
  }
}

onunhandledrejection

onunhandledrejection是浏览器事件,可以捕获异步的代码错误,包括:

  1. 事件处理函数(client-side)中的异步错误
  2. asyncData(server-side)中的错误

DEMO in plugins - NuxtJS

/**
 * @file plugins/monitor.client.js
 */

export default function (ctx) {
  window.onunhandledrejection = (event) => {
    console.log('[onunhandledrejection 错误处理]: ', event, event.reason)
  }
}

render:errorMiddleware

render:errorMiddleware是NuxtJS内部向外暴露的一个hook,他本质上是添加一个connect的错误中间件,而connect是NuxtJS底层用于实现HTTP Server的框架。

值得关注的是,在render:errorMiddleware中你并不能阻止错误继续传播下去,也就是说你不能阻止 静态错误页 的展示。如果想避免静态错误页的展示,你需要在asyncData中捕获并处理掉这些错误。

DEMO in The hooks Property - NuxtJS

/**
 * @file hooks/render.js
 */

export default (nuxtConfig) => ({
  errorMiddleware(app) {
    app.use((error, _req, _res, next) => {
      if (error) {
        console.log('[errorMiddleware 错误处理]: ', error)
      }

      // 将传递给后面的错误中间件继续处理
      next(error)
    })
  },
})

错误页面

若不进行错误的处理,错误将最终被展示出来,有以下三种形式:

  1. 浏览器Console
  2. NuxtJS错误页
  3. 静态错误页

浏览器Console

事件处理函数中的错误会仅会展示到浏览器的Console(控制台)上,不会导致页面的崩溃(即我们常说的白屏)。

NuxtJS错误页

客户端的asyncData错误和模版渲染错误会展示NuxtJS错误页。使用 context.error方法也会导向该页面。

image.png

你可以通过添加layouts/error.vue文件来覆盖默认的NuxtJS错误页。

DEMO in layouts/error.vue

/**
 * @file layouts/error.vue
 */

@Component({
  props: {
    error: {
      type: Object,
      default: () => ({}),
    },
  },
})
export default class ErrorPage extends Vue {
  mounted() {
    console.log('[layouts/error 错误展示]: ', error)
  }
}

静态错误页

服务端的asyncData错误和模版渲染错误会展示静态错误页:

image.png

但是在开发环境下,你不会看见如上页面,会改为展示 youch 错误页面

image.png

你可以通过添加app/views/error.html文件来覆盖默认的静态错误页。

DEMO in app/views/error.html

/**
 * @file app/views/error.html
 */

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>错误页</title>
</head>
<body>
  <h1>服务器崩溃了,嘤嘤嘤~</h1>
</body>
</html>