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

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

// 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', '.*');
        });
    }
);

 末尾の

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

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

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

        {
            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