エラーハンドリング

開発

堅牢なサーバーサイドフレームワークを使用する利点の1つは、無料で利用できる組み込みの例外処理です。たとえば、Laravelには、ローカル開発で適切にフォーマットされたスタックトレースを表示する美しいエラーレポートツールであるIgnitionが付属しています。

問題は、XHRリクエスト(Inertiaが行う)を実行中にサーバー側のエラーが発生した場合、通常、ブラウザの開発者ツールのネットワークタブを調べて問題を診断する必要があることです。

Inertiaはこの問題を、Inertia以外のすべてのレスポンスをモーダルで表示することで解決します。つまり、XHR経由でリクエストを行った場合でも、使い慣れた美しいエラーレポートを利用できます。

読み込み中…

本番環境

本番環境では、開発中に存在するモーダル駆動のエラーレポートに依存するのではなく、適切なInertiaエラーレスポンスを返したいでしょう。これを実現するには、フレームワークのデフォルトの例外ハンドラーを更新して、カスタムエラーページを返す必要があります。

Laravelアプリケーションを構築する場合、アプリケーションのbootstrap/app.phpファイルでrespond例外メソッドを使用することでこれを実現できます。

use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Inertia\Inertia;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->respond(function (Response $response, Throwable $exception, Request $request) {
        if (! app()->environment(['local', 'testing']) && in_array($response->getStatusCode(), [500, 503, 404, 403])) {
            return Inertia::render('Error', ['status' => $response->getStatusCode()])
                ->toResponse($request)
                ->setStatusCode($response->getStatusCode());
        } elseif ($response->getStatusCode() === 419) {
            return back()->with([
                'message' => 'The page expired, please try again.',
            ]);
        }

        return $response;
    });
})

上記の例では、Errorページコンポーネントを返していることに気づいたかもしれません。実際には、アプリケーションの一般的なエラーページとして機能するこのコンポーネントを作成する必要があります。以下に、開始点として使用できるエラーコンポーネントの例を示します。

<script setup>
import { computed } from 'vue'

const props = defineProps({ status: Number })

const title = computed(() => {
  return {
    503: '503: Service Unavailable',
    500: '500: Server Error',
    404: '404: Page Not Found',
    403: '403: Forbidden',
  }[props.status]
})

const description = computed(() => {
  return {
    503: 'Sorry, we are doing some maintenance. Please check back soon.',
    500: 'Whoops, something went wrong on our servers.',
    404: 'Sorry, the page you are looking for could not be found.',
    403: 'Sorry, you are forbidden from accessing this page.',
  }[props.status]
})
</script>

<template>
  <div>
    <H1>{{ title }}</H1>
    <div>{{ description }}</div>
  </div>
</template>