Search code examples
vuejs2vue-routerlaravel-7

Vue router doesn't work with complex routes


I am making a single page application with laravel 7, vue cli 2 and vue-rotuer 3.

I have created a "router.js" file where I declare all the routes inside. Simple routes like "/" or "/blog" work, but when I put a second slash, I get error 404 on the page. I had to create a dynamic route (/blog/:slug), but a static route with a double slash (/blog/post) does not work either.

No error is shown either in php artisan serve or in npm run watch, the console shows "GET http://127.0.0.1:8000/blog/test 404 (Not Found)".

I have tested the various vue components (Home, Blog, PostDetails) and they are rendered correctly on the page, so the error is not triggered by them.

I initially installed vue-router with npm install vue-router@3, but then I tried installing another version of vue-router (v3.5.3), which I had already worked with without any problems, but it still does not work.

I have also tried the project on both mac os and windows, but the result does not change.

Vue-router version

package.json

{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "npm run development -- --watch",
        "watch-poll": "npm run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "npm run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.19",
        "bootstrap": "^4.0.0",
        "cross-env": "^7.0",
        "jquery": "^3.2",
        "laravel-mix": "^5.0.1",
        "lodash": "^4.17.19",
        "popper.js": "^1.12",
        "resolve-url-loader": "^2.3.1",
        "sass": "^1.20.1",
        "sass-loader": "^8.0.0",
        "vue": "^2.5.17",
        "vue-template-compiler": "^2.6.10"
    },
    "dependencies": {
        "vue-router": "^3.5.3"
    }
}

Established the php routes

routes > web.php

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Auth::routes();

Route::middleware('auth')
    ->namespace('Admin')
    ->name('admin.')
    ->prefix('admin')
    ->group(function () {
        Route::get('/', 'HomeController@index')->name('home');

        // Post Routes
        Route::resource('/posts', 'PostController');

        // Category Routes
        Route::get('/categories', 'CategoryController@index')->name('categories');
        Route::get('/categories/{slug}', 'CategoryController@show')->name('category_info');

        // User Routes
        Route::get('/user/show', 'UserController@showUser')->name('user.show');
        Route::get('/user/edit', 'UserController@editUser')->name('user.edit');
        Route::put('/user/update', 'UserController@updateUser')->name('user.update');
    });

Route::get("{any?}", function() {
    return view('guests.home');
});

I imported vue-router correctly

front.js

window.Vue = require('vue');
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

/**
 * The following block of code may be used to automatically register your
 * Vue components. It will recursively scan this directory for the Vue
 * components and automatically register them with their "basename".
 *
 * Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
 */

// const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))

import App from './views/App.vue';
import router from './router.js';

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */

const app = new Vue({
    el: '#root',
    render: h => h(App),
    router
});

The file with the declared routes

router.js

import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter)

import Home from './pages/Home.vue';
import Blog from './pages/Blog.vue';
import PostDetails from './pages/PostDetails.vue';

const router = new VueRouter({
    mode: "history",
    routes: [
        {
            path: "/",
            name: "home",
            component: Home,
        },
        {
            path: "/blog",
            name: "blog",
            component: Blog,
        },
        {
            path: "/blog/:slug",
            name: "post-details",
            component: PostDetails,
        }
    ]
});

export default router;

Vue components

pages > Home.vue

<template>
    <h1>Hi, I'm Home!</h1>
</template>

<script>
export default {
    name: 'Home',
}
</script>

pages > Blog.vue

<template>
    <h1>Hi, I'm Blog!</h1>
</template>

<script>
export default {
    name: 'Blog',
}
</script>

pages > PostDetails.vue

<template>
    <h1>Hi, I'm PostDetails!</h1>
</template>

<script>
export default {
    name: 'PostDetails',
}
</script>

I hope you can help me, thank you.


Solution

  • I found the problem. Basically I forgot to put this string in the routes > web.php file:

    ->where('any', '.*')

    Before:

    Route::get("{any?}", function() {
        return view('guests.home');
    });
    

    After:

    Route::get("{any?}", function() {
        return view('guests.home');
    })->where('any', '.*');