こんにちは、”はふぃ”です。
今回は Nuxt.js を使ったエラーページに関する話をしたいと思います。
エラーページとは
エラーページはその名の通り、サイト上でなんらかの不具合(エラー)が発生した時にユーザーにそれを伝えるためのページのことです。

上記のようにエラーページには三桁の数字(画像では404)が表示されていることが多いのですが、これは HTTPステータスコード と呼ばれるもので、なんのエラー(エラー以外もありますが)が発生しているのかをコードごとに示すものとなります。
エラーに関する HTTPステータスコード だと 400系 と 500系 があり、400系 がクライアントエラー(ユーザー操作などで発生するエラー)で 500系 がサーバーエラー(システム側でのエラー)を表します。
例えば、上の画像の 404 というエラーは「そんなページは存在しません」というコードなのですが、ページにアクセスするためのURLを入力するのはユーザーで、それが間違っているというエラーなのでクライアントエラーである400系に分類されているというわけです。
以下に代表的な400系と500系のエラーを紹介します。
- 400系(クライアントエラー)
- 400(Bad Request):クライアントからサーバーへのリクエストに何らかの不備がある
- 403(Forbidden):アクセス権がないページにアクセスするなどサービス側で禁止している
- 404(Not Found):ページが見つからない
- 500系(サーバーエラー)
- 500(Internal Server Error):サーバー側で処理方法が分からないエラーが発生した
- 503(Service Unavailable):サーバーがダウンしていたりメンテナンス中などサービスが利用できない状態
エラーページ作成
では、ここから実際にコードや画面で説明しながらエラーページを作っていきます。
Nuxt.js では layouts/error.vue
にエラーページのデザインや処理を記入することで全ページ共通のエラーページを作成することができます。
< layouts/error.vue >
<template> <div> <h1>{{ error.statusCode }}</h1> <h1>エラーが発生しました</h1> </div> </template> <script> export default { props: { error: { type: Object, default () { return {} } } } } </script>
このページでは標準で error
というObjectのpropsが渡され、その中に先ほど紹介した HTTPステータスコード を表す statusCode
という値を持っています。
statusCode の値はデフォルトでは404なので、例えば /aaa のような存在しないページのURLでアクセスすると以下のような表示になります。
※ わかりやすくするために枠線をひいています

エラーハンドリング(エラーページの表示制御)
エラーページが作成できたので、ここからはエラーハンドリング(発生したエラーに応じて処理を使い分ける)をしながらエラーページをカスタマイズしていこうと思います。
基本的なエラーハンドリング
まずは Nuxt.js の fetch 処理の中でAPIを使ってデータを取得する場面を想定してエラーハンドリングしてみましょう。
API側でエラーが発生した場合はシステムのエラーなので 500系 が使われます。
今回は50%で失敗する(現実ではありえませんが。笑)処理をAPIからデータを取得する処理と仮定して、うまくいった場合には 400 エラーを返す以下のような処理で試してみます。
< pages/sample/errorPage.vue >
<template> <div /> </template> <script> export default { fetch ({ error }) { const fetchFn = () => { // 50%で失敗する if (parseInt(Math.random() * 2, 10) === 1) { throw new Error('server error') } return true } try { // 処理が成功したら400, 失敗したら500 fetchFn() error({ statusCode: 400 }) } catch (e) { error({ statusCode: 500 }) } } } </script> <style></style>


なお、Nuxt.js の error メソッドを使った場合、エラーページが表示される際にURLが変わらない( /error
などにならない)という特徴があるのでサイトによっては注意が必要です!(Google Analyticsなどのツールを使って後からエラー率を取得しようとしている場合など)

バリデーション(validate)を使ったエラー
Nuxt.js では validate という機能を使って、ページにアクセスしてきた時にURLパラメータやURLクエリーが正しいかをチェックすることができます。
先ほどのコードに以下のようなvalidate処理を追加してみましょう。
< pages/sample/errorPage.vue >
… <script> export default { validate ({ query }) { return query.sampleId }, fetch ({ error }) { …
今回は sampleId
というqueryがついていない場合はバリデーションで弾くような実装にしました。
○:http://localhost:3000/sample/errorPage?sampleId=1
×:http://localhost:3000/sample/errorPage
これで↑の × のパターンのURLでアクセスすると以下のように404エラーの表示になります。
※ validateエラーのstatusCodeは404になります

エラーメッセージを動的に表示
Nuxt.js の error メソッドでは statusCode の他に message
というパラメータでエラーメッセージも渡すことができます。
これを使うことでエラーごとに任意のエラーメッセージをエラーページで表示させることが可能です。
< pages/sample/errorPage.vue >
… try { // 処理が成功したら400, 失敗したら500 fetchFn() error({ statusCode: 400, message: '操作にミスがあります。最初からやり直してください。' }) } catch (e) { error({ statusCode: 500, message: 'システムがダウンしています。時間をおいてやり直してください。' }) } …
< layouts/error.vue >
<template> <div> <h1>{{ error.statusCode }}</h1> <h1>{{ error.message }}</h1> </div> </template> …


さらに layouts/error.vue
でも処理を追加してエラーメッセージを切り替えてみましょう。
< layouts/error.vue >
<template> <div> <h1>{{ error.statusCode }}</h1> <h1>{{ errorMessage }}</h1> </div> </template> <script> export default { props: { error: { type: Object, default () { return {} } } }, computed: { errorMessage () { if (this.error.statusCode === 404) { return 'ページが存在しません' } if (this.error.message) { return this.error.message } return 'エラーが発生しました' } } } </script>
この状態で先ほどのバリデーションエラーを発生させると、このように設定したエラーメッセージが表示されます。

まとめ
Nuxt.js は layouts/error.vue
をいじるだけでエラーページをいじれるので便利ですね!
参考
今回のコードはgithubで公開中なので参考にしてみてください!↓
https://github.com/hafilog/vue-sample/tree/master/components/pages/sample