Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle Nuxt SSR errors and show custom 404 || 500 pages?

How do you handle errors when Nuxt's SSR runs into an error?

Currently i am using error() handler but it doesn't work in the production? This is the example of my Nuxt app.

asyncData

 async asyncData({ store, route, error }) {
    return store.dispatch( NAMESPACES.USERS + ACTIONS.GET_DETAIL, userId ).then(response => ({
      data: response,
    })).catch((e) => {
      error(e)
    })
  } 

error.vue

  <vis-container>
    <vis-row class="error">
      <vis-col md="8" class="error__component">
        <component :is="errorPage" :error="error.statusCode" />
      </vis-col>

      <vis-col md="8" class="error__contact">
        <p class="error__contact__title">{{ $t('error_page.question') }}</p>
      </vis-col>
    </vis-row>
  </vis-container>
</template>

<script>
export default {
  props: ['error'],
components: {
    NotFound: () => import('@/components/error/NotFound'),
    InternalServerError: () => import('@/components/error/InternalServerError'),
  },
    computed: {
    errorPage() {
      if (this.error.statusCode === 500) {
        return 'InternalServerError'
      }

      return 'NotFound'
    },
  },
}
</script>

like image 369
Miloslavc Avatar asked Oct 10 '19 14:10

Miloslavc


1 Answers

This answer is only relevant for SSR mode.

There are different possible type of errors. I will provide here info about 2 types of them:

  • errors in dynamic routes
  • errors during data fetching (nuxt >= 2.12, fetch hook)

Errors handling for dynamic routes [Option 1]:

According to Nuxt docs about lifecycle there is a special validate hook. It's main purpose to validate dynamic routes parameters.
Here you can find more detailed description, but in general you need to provide validate implementation which supposed to return true when params are valid and false when they are not.
In case of false nuxt will return 404 response with default error page (you can also throw expected or unexpected errors during validate function execution as well as customize default error page).
Important note here:

This method takes the context object as an argument.

Errors handling for dynamic routes [Option 2]:

Whenever you need to return different status codes for server-side rendered pages in Nuxt, you need to use middleware.

This is the main idea - you have to define your own middleware to verify url here (probably with async logic inside).

import { Context } from "@nuxt/types";
import { isUrlValid } from "~/services/validateRoute";

export default async function (context: Context) {
  if (!(await isUrlValid(context.route.path))) {
    context.error({
      statusCode: 404,
      message: `Invalid route: ${context.route.path}`,
    });
  }
}

And to make it work, it should be linked to the corresponding dynamic route page:

import Vue from "vue";
import Component from "vue-class-component";
@Component({
  middleware: "validateRoute",
})
export default class RedirectPage extends Vue {}

Working app example is here: https://github.com/DamirsCorner/20210521-nuxt-dynamic-route-404

Source: https://www.damirscorner.com/blog/posts/20210521-404PageForNuxtDynamicNestedRoutes.html

Data fetching errors handling:

Nuxt docs says:

If there is an error when fetching data, the normal Nuxt error page won't be loaded - and you should not use the Nuxt redirect or error methods within fetch(). Instead, you will need to handle it within your component using $fetchState.error.

So, it's pretty straightforward:

<template>
  <div>
    <p v-if="$fetchState.pending">Loading....</p>
    <p v-else-if="$fetchState.error">Error while fetching mountains</p>
    <ul v-else>
      <li v-for="(mountain, index) in mountains" :key="index">
        {{ mountain.title }}
      </li>
    </ul>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        mountains: []
      }
    },
    async fetch() {
      this.mountains = await fetch(
        'https://api.nuxtjs.dev/mountains'
      ).then(res => res.json())
    }
  }
</script>

From this example you can see that you won't be able to change response code, since error in that stage will be interpreted as normal situation with 200 response code.

like image 109
evg_ny Avatar answered Nov 16 '22 15:11

evg_ny