【Vue.js】LaravelとVueRouterの組み合わせで404エラーページを見せる

 LaravelをAPIに専念させてVue.jsにフロントエンドを任せる、という構成でwebサイトを作ることを考えます。そうした時、Laravel側のルーティングはおおよそ次の様になります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// web.php
Route::group(
    static function () {
        // ログイン
        Route::get('login', 'Auth\LoginController@showLoginForm')->name('login');
        Route::post('login', 'Auth\LoginController@login')->name('login');
        Route::post('logout', 'Auth\LoginController@logout')->name('logout');
        // 本体
        Route::middleware(['auth:web'])->group(static function () {
            // API
            Route::prefix('api')->name('api.')->group(static function () {
                Route::get('member/search', 'MemberController@search')->name('member.search');
                Route::apiResource('member', 'MemberController', ['show', 'update']);
            });
            // Vue.jsアプリへのアクセス
            Route::get('/{any}', static function () {
                return view('pages.index');
            })->where('any', '.*');
        });
    }
);

 末尾の

1
2
3
Route::get('/{any}', static function () {
    return view('pages.index');
})->where('any', '.*');

で上からルーティングを読んでいき、当てあはまらなかった全てのルーティングをキャッチしてindexページを返します。indexページの中にはVue.jsのアプリページが入っています。
 このようにするとLaravel側はVue.js側のルーティングに対してほぼ完全に無関心になります。無関心故に404も返せなくなります。Vue.js側で404を実装する必要が出てきます。
 まずはルーティングにキャッチできなかった謎URLを全て404にするルーティングの定義です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import Vue from 'vue';
import Router, {RouterOptions} from 'vue-router';
import IndexPage from '@/pages/Index';
import MemberIndexPage from '@/pages/member/Index';
 
Vue.use(Router);
 
const options: RouterOptions = {
    mode: 'history',
    routes: [
        {
            path: '/',
            name: 'root',
            component: IndexPage,
        },
        {
            path: '/member',
            name: 'member',
            component: MemberIndexPage,
        },
        {
        // ここで上のルーティングに該当しなかったものを全てNotFoundPage送り
            path: '*',
            name: 'notFound',
            component: NotFoundPage,
        },
    ],
};
 
export default new Router(options);

 少し手間なのがAPIの結果によってページが存在するかしないか判断する場合です。そういった際はbeforeEnterというルート単位ガード処理を定義し、その中でリダイレクトさせるとNotFoundPage送りにできます。
ナビゲーションガード | Vue Router

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
    path: '/member/:id',
    name: 'memberShow',
    component: MemberShow,
    beforeEnter: (to, from, next) => {
        MemberRepository.find(to.params.id).then((member) => {
            to.meta.member = member;
            next();
        }).catch((e) =>{
    // APIの結果が例外処理ならば、とりあえず404送り。/404に該当するルーティングはないのでNotFoundPage送り
            next({path: '/404', query: {msg: '存在しない会員のIDです'}});
        });
    },
    props: (route)=> {
        return {member: route.meta.member};
    },
},
>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG