エラーハンドリング

開発

堅牢なサーバーサイドフレームワークで作業する利点のひとつは、例外ハンドリングが最初から組み込まれていることです。たとえば、Laravel には美しいエラーレポートツールが同梱されており、ローカル開発時に整形されたスタックトレースを表示してくれます。

課題となるのは、XHR リクエスト(Inertia が行っているもの)を送信してサーバーサイドでエラーが発生した場合、問題を診断するためにブラウザの開発者ツールのネットワークタブを掘り下げる必要がある点です。

Inertia はこの問題を、Inertia 以外のすべてのレスポンスをモーダルで表示することで解決します。これにより、XHR 経由のリクエストであっても、慣れ親しんだ美しいエラーレポートをそのまま利用できます。

Dialog 要素

デフォルトでは、Inertia はカスタムの <div> オーバーレイを使用してエラーモーダルを表示します。しかし、代わりにネイティブの HTML <dialog> 要素を使用するようオプトインすることもできます。これにより、バックドロップ処理を含む組み込みのモーダル機能を利用できます。

これを有効にするには、アプリケーションのデフォルト設定future.useDialogForErrorModal オプションを設定してください。

js
createInertiaApp({
    // resolve, setup, etc.
    defaults: {
        future: {
            useDialogForErrorModal: true,
        },
    },
})

本番環境

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

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

php
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('ErrorPage', ['status' => $response->getStatusCode()])
                ->toResponse($request)
                ->setStatusCode($response->getStatusCode());
        }

        if ($response->getStatusCode() === 419) {
            return back()->with([
                'message' => 'The page expired, please try again.',
            ]);
        }

        return $response;
    });
})

上記の例では ErrorPage というページコンポーネントを返していることにお気づきかもしれません。このコンポーネントを実際に作成する必要があります。これはアプリケーション全体で使用される汎用的なエラーページとなります。以下は、出発点として使えるエラーコンポーネントの例です。