Nuxt3 でカスタムエラーページを作成する

Nuxt3のエラーハンドリングが、Nuxt2から変わりました。
2023.10.24

Nuxt3が 2022年11月にリリースされてから、もうすぐ1年が経過します。 Nuxt2を元々利用していて、Nuxt3への移行作業を進めている方も多くいらっしゃるのではないでしょうか。

Nuxt2 から Nuxt3 にかけて、カスタムエラーページの表示方法が変化しています。 少々躓くポイントがあったので、Nuxt3でのカスタムエラーページの表示方法を紹介していきます。

実際に動くコードを見たい方は、サンプルコードを作成したので以下のページをご覧ください。

Nuxt3 エラーハンドリング サンプル - StackBlitz

やりたかったこと

  • 404, 500 などエラータイプに応じて適切なエラーページを表示したい
  • エラーページのテンプレートは1つにしたい。

基本的にNuxt2でやっていることをそのままやりたい気持ちです。

結論:プロジェクトルートにerror.vueを配置する

早速結論ですが、プロジェクトルートに error.vue を配置することでこれらの課題を解決できます。

注意点としては、 app.vue ではなく pages ディレクトリを使用している場合でもプロジェクトルートに配置する必要があります。 なので、ディレクトリ構成は以下のようになります。

pages/
	index.vue
	signup.vue
error.vue		←ここに置く!
nuxt.config.ts
package.json
...

ここがNuxt2から変化した部分です。

Nuxt2では pages ディレクトリを使用している場合は、 pages ディレクトリ配下に error.vue を置くことでカスタムエラーページを作成できていました。 しかし、Nuxt3では pages ディレクトリに error.vue を配置しても認識されず、Nuxt標準のエラーページが出てきてしまいます。

ですので、Nuxt3ではカスタムエラーページを作成したい場合、プロジェクトルートに error.vue を配置するようにしましょう。

活用:エラーコードに応じて表示する内容を変えてみる

カスタムエラーページを表示できるようになりましたが、このままだと固定のページしか表示できません。 今回はステータスコードに対応したエラーメッセージを返せるようにしてみます。

やること

  • error.vueでステータスコードを受け取る
  • ステータスコードに応じて事前に用意したエラーテンプレートを表示する
  • エラーを発生させる

error.vue でステータスコードを受け取る

Nuxt3では、エラーが発生した際に errorという変数名で値を受け取ることができます。 以下のように記述することで、error 変数からステータスコードを取り出すことができます。

#/error.vue

interface Props {
  error: Object;
}
const props = defineProps<Props>();

onMounted(() => {
  console.log(props.error.statusCode); // 403, 404 など
});

エラーオブジェクトの中身には、statusCodeの他にも以下のようなパラメータが存在しています。

{
  url: string
  statusCode: number
  statusMessage: string
  message: string
  description: string
  data: any
}

ステータスコードに応じて事前に用意したエラーテンプレートを表示する

error.vue では、コンポーネントを import して使用することもできます。 以下のように、ステータスコードに応じたコンポーネントを返却してみます。

#/error.vue

<script lang="ts" setup>
import error403 from '~/components/403.vue';
import error404 from '~/components/404.vue';
import error500 from '~/components/500.vue';

// Props
interface Props {
  error: Error;
}
const props = defineProps<Props>();

// Valiables
const errorPage = computed(() => {
  if (props.error.statusCode === 403) {
    return error403;
  } else if (props.error.statusCode === 404) {
    return error404;
  } else {
    return error500;
  }
});

// Functions
const handleError = () => clearError({ redirect: '/' });
</script>

<template>
  <div>error.vue</div>
  <component :is="errorPage" />
  <button @click="handleError">Back home</button>
</template>

#/components/403.vue

<template>
  <main>
    <h1>アクセスが拒否されました。</h1>
    <div>ページを表示できません。</div>
  </main>
</template>

props.error.statusCodeの値に応じたコンポーネントをerrorPage変数に格納し、 component 要素の is属性を使って動的にコンポーネントを変更しています。

エラーを発生させる

では、実際にエラーを発生させてみましょう。Nuxt3では、showError関数を使用することで、任意の場所でエラーを発生させることができます。引数には、statusCode 以外にも前述のパラメータを指定することができます。

では、即座に403エラーを発生させるページを作成してみます。

#/pages/403.vue

<script setup>
showError({ statusCode: 403 });
</script>
<template>
  <div>403.vue</div>
</template>

このページに訪問すると、以下のような画面が表示されます。 Nuxt3の403エラー サンプルページ

意図した通り、pages/403.vue のテンプレートは表示されず error.vue を通じて403エラーの内容が表示されていることがわかります。

注意点

Nuxt 3.7.4 現在、以下の注意点があります。

  • layouts は使えない
  • Vuetify などプラグインによって使用しているライブラリも使えない

ドキュメントには記述が見当たりませんでしたが、error.vue では layouts ファイルは機能しないようです。 個別にコンポーネントを import することはできるので、記事で紹介したように import して使用するようにしましょう。
また、Vuetifyなどのプラグインを使用したライブラリも使用できません。エラーページなので、リッチな機能が必要になるケースは少ないかと思いますが、注意しましょう。

サンプルコード

今回紹介したサンプルコードは以下のページで動作を確認することができます。 実際に触って、ファイルの構成や動きなどを確認してみてください。