nuxt logo

ドキュメント翻訳(非公式)

エラー処理

Nuxtでエラーをキャッチして処理する方法を学びます。

Nuxtはフルスタックフレームワークであるため、異なるコンテキストで発生する可能性のあるいくつかの予防不能なユーザーランタイムエラーの原因がいくつかあります:

  • Vueレンダリングライフサイクル中に発生するエラー(SSR & CSR)
  • サーバーおよびクライアントの起動エラー(SSR + CSR)
  • Nitroサーバーライフサイクル中のエラー(server/ディレクトリ)
  • JSチャンクのダウンロードエラー

SSRServer-Side Rendering(サーバーサイドレンダリング)の略であり、CSRClient-Side Rendering(クライアントサイドレンダリング)の略です。

Vueエラー

Vueのエラーに関しては、onErrorCapturedを使用してフックことができます。

加えて、Nuxtはトップレベルまでエラーが伝播した場合に呼ばれるvue:errorフックを提供しています。

エラー報告フレームワークを使用している場合は、vueApp.config.errorHandlerを通じてグローバルハンドラーを提供することができます。これは処理されたものを含むすべてのVueエラーを受け取ります。

plugins/error-handler.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
    // handle error, e.g. report to a service
  }

  // Also possible
  nuxtApp.hook('vue:error', (error, instance, info) => {
    // handle error, e.g. report to a service
  })
})

vue:errorフックは、onErrorCapturedライフサイクルフックに基づいています。

起動エラー

Nuxtアプリケーションの起動中にエラーが発生した場合、Nuxtはapp:errorフックを呼びます。

これには以下が含まれます:

  • Nuxtプラグインの実行
  • app:createdおよびapp:beforeMountフックの処理
  • HTMLへのVueアプリのレンダリング(SSR中)
  • アプリのマウント(クライアントサイド)、ただし、この場合はonErrorCapturedまたはvue:errorで処理する必要があります
  • app:mountedフックの処理

Nitroサーバーエラー

現在、これらのエラーのサーバーサイドハンドラーを定義することはできませんが、エラーページをレンダリングすることができます。詳細についてはエラーページをレンダリングするセクションをご覧ください。

JSチャンクのエラー

ネットワーク接続の障害や新しいデプロイメント(古いハッシュ化されたJSチャンクURLを無効にする)により、チャンク読み込みのエラーが発生することがあります。Nuxtはルートナビゲーション中にチャンクの読み込みに失敗した場合、ハードリロードを実行することにより、チャンク読み込みエラーを処理するための組込みサポートを提供しています。

この挙動を変更するには、experimental.emitRouteChunkErrorfalseに設定する(これらのエラーをまったくフックしないようにするため)か、それらを自分で処理したい場合はmanualに設定します。チャンクの読み込みエラーを手動で処理したい場合は、自動実装例を参考にすることができます。

エラーページ

Nuxtが致命的なエラー(サーバー上の処理されていないエラー、またはクライアント上でfatal: trueで作成されたエラー)に遭遇した場合、Accept: application/jsonヘッダーで要求された場合はJSONレスポンスをレンダリングするか、全画面のエラーページをトリガーします。

サーバーライフサイクル中にエラーが発生する場合があります:

  • Nuxtプラグインの処理中
  • HTMLへのVueアプリのレンダリング中
  • サーバーAPIルートがエラーをスローする場合

クライアントサイドでは、以下の場合に発生することがあります:

  • Nuxtプラグインの処理中
  • アプリケーションのマウント前(app:beforeMountフック)
  • onErrorCapturedまたはvue:errorフックで処理されなかった場合のアプリのマウント時
  • ブラウザでVueアプリが初期化され、マウントされたとき(app:mounted)。
こちらも参照 api > advanced > hooks

アプリケーションのソースディレクトリに~/error.vueを追加することで、デフォルトのエラーページをカスタマイズすることができます。これはapp.vueと並行して配置します。

error.vue
<script setup lang="ts">
import type { NuxtError } from '#app'

const props = defineProps({
  error: Object as () => NuxtError
})

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

<template>
  <div>
    <h2>{{ error?.statusCode }}</h2>
    <button @click="handleError">エラーをクリア</button>
  </div>
</template>
こちらも参照 guide > directory-structure > error

最後に

ページやコンポーネントのセットアップ関数で呼び出せるonErrorCapturedコンポーザブル, またはNuxtプラグインで設定できるvue:errorランタイムフックを使用することを強く推奨します。

plugins/error-handler.ts
export default defineNuxtPlugin(nuxtApp => {
  nuxtApp.hook('vue:error', (err) => {
    //
  })
})

エラーページを削除準備ができたら、オプションでリダイレクト先を指定する(例えば、'安全'なページにナビゲートしたい場合)clearErrorヘルパー関数を呼び出すことができます。

Nuxtプラグインに依存するものを使用する前に必ずチェックしてください。例えば、$routeuseRouterなどは、プラグインがエラーを投げた場合、エラーをクリアするまで再実行されません。

エラーページをレンダリングすることは、完全に別のページロードを意味します。つまり、登録されたすべてのミドルウェアが再度実行されます。ミドルウェアでエラーが処理されているかどうかを確認するためにuseErrorを使用することができます。

Node 16を使用しており、エラーページのレンダリング時に任意のクッキーを設定する場合、それらは以前に設定されたクッキーを上書きします。Node 16は2023年9月にサポート終了になったため、より新しいバージョンのNodeの使用をおすすめします。

エラーユーティリティ

useError

TS Signature
function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>

この関数は処理中のグローバルNuxtエラーを返します。

こちらも参照 api > composables > use-error

createError

TS Signature
function createError (err: string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error

追加のメタデータを持つエラーオブジェクトを作成します。エラーmessageとして設定される文字列を渡すことも、エラープロパティを含むオブジェクトを渡すこともできます。この関数はアプリのVueおよびサーバー部分で使用でき、投げられることを意図しています。

createErrorで作成したエラーを投げると:

  • サーバーサイドでは、clearErrorでクリアできる全画面エラーページをトリガーします。
  • クライアントサイドでは、処理すべき非致命的なエラーを投げます。全画面エラーページをトリガーする必要がある場合は、fatal: trueを設定することができます。
pages/movies/[slug\
const route = useRoute()
const { data } = await useFetch(`/api/movies/${route.params.slug}`)

if (!data.value) {
  throw createError({
    statusCode: 404,
    statusMessage: 'Page Not Found'
  })
}
こちらも参照 api > utils > create-error

showError

TS Signature
function showError (err: string | Error | { statusCode, statusMessage }): Error

この関数はクライアントサイドで、または(サーバーサイドで)ミドルウェア、プラグインまたはsetup()関数内で直接呼び出すことができます。これにより、clearErrorでクリアできる全画面エラーページがトリガーされます。

代わりにthrow createError()を使用することを推奨します。

こちらも参照 api > utils > show-error

clearError

TS Signature
function clearError (options?: { redirect?: string }): Promise<void>

この関数は現在処理中のNuxtエラーをクリアします。また、オプションでリダイレクト先を指定することもできます(例えば、'安全'なページにナビゲートしたい場合)。

こちらも参照 api > utils > clear-error

コンポーネント内でエラーをレンダリング

Nuxtは<NuxtErrorBoundary>コンポーネントも提供しており、アプリ内のクライアントサイドエラーを取り扱うことができます。これにより、サイト全体をエラーページに置き換えることなくエラーを処理することが可能です。

このコンポーネントは、そのデフォルトスロット内で発生するエラーを処理する責任を持ちます。クライアントサイドでは、エラーがトップレベルにバブルアップするのを防ぎ、代わりに#errorスロットをレンダリングします。

#errorスロットはerrorをプロパティとして受け取ります。(error = nullに設定すると、デフォルトスロットの再レンダリングがトリガーされますが、エラーが完全に解決されていない場合、エラースロットが再度レンダリングされることになります。)

別のルートにナビゲートすると、エラーは自動的にクリアされます。

pages/index.vue
<template>
  <!-- some content -->
  <NuxtErrorBoundary @error="someErrorLogger">
    <!-- You use the default slot to render your content -->
    <template #error="{ error, clearError }">
      エラーをここにローカルで表示: {{ error }}
      <button @click="clearError">
        これによりエラーがクリアされます。
      </button>
    </template>
  </NuxtErrorBoundary>
</template>
サンプルコードの編集とプレビューexamples > advanced > error-handling