How to combine the VueJS Router with Laravel

I’m a huge fan of Laravel and like to code whenever I have some spare time. More recently I also started with VueJS, which is definitely making more sense when you want to offer a very rich and dynamic user experience. One of my biggest challenges has been to combine both the VueJS Router and Laravel routing concepts. I wanted to use the Laravel back-end and authentication methods provided, but I also wanted to use VueJS for some more dynamic parts. We can of course add the VueJS template and script elements to every blade we create, but the result is that every time the page will be reloaded. This is not something we want. We want to use Vue Resource in order to create an application without the need to reload everytime we change the route. How can we do that, when working with Laravel?

To start with we need to have NodeJS. Download your install from the NodeJS website or use the command line to install NodeJS. Also make sure that you are least using Laravel 5.4. After the installation of NodeJS, make sure both of these commands are working:

node -v
npm -v

The next step is to install all relevant packages:

npm install

If you are using Windows, you might need to run the following command as well to install all relevant build packages:

npm install — global — production windows-build-tools

Next step is that we will add VueJS to our project. Run the following command:

npm install vue

In addition we also want to have the vue-router component to be installed. Run the following command:

npm install vue-router

You can also use my package.json and run the npm install command again.

{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"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 --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 --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.16.2",
"bootstrap-sass": "^3.3.7",
"cross-env": "^5.0.5",
"jquery": "^3.1.1",
"laravel-mix": "^1.0",
"lodash": "^4.17.4",
"vue": "^2.1.10"
},
"dependencies": {
"vue-router": "^2.7.0"
}
}

If everything is working it’s time to create the VueJS components. I’m using a very easy example here. I have Home component and another component called Example in the routes file. Create the following file:

resources/assets/js/vue-app.js (I’m using vue-app.js, because the app.js probably might already exist)

import Vue from 'vue'
import VueRouter from 'vue-router';
import Home from './components/Home.vue';
import { routes } from './routes';Vue.use(VueRouter);const router = new VueRouter({
mode: 'history',
routes
});
new Vue({
el: '#app',
router
});

Next step is to create the routes file: resources/assets/js/routes.js

Please note that I’m using the /vue/ directory here. You can add many directories, but you need to be aware that later in this tutorial we will force Laravel to not reload this route. VueJS will basically take over the routing part from here.

import Home from './components/Home.vue';
import Example from './components/Example.vue';
export const routes = [
{ path: '/vue', component: Home, name: 'Home' },
{ path: '/vue/example', component: Example, name: 'Example' }
];

As you can see we have the Home component and also the Example component registered here.

Next step is to create two more files. Create the following directory: resources/assets/js/components/ and let’s create our first Vue Component, called Home.Vue

<template>
@{{ message }}
<router-link to="/vue/example"><a>url to example</a></router-link>
</template>
<script>
export default {
data () {
return {
message: 'This is the home component!'
};
}
};
</script>

As you can see it is a very simple component and it will only display that the home component is loaded. Next step is to create the Example component. Create another file called Example.Vue

<template>
<h3>This shows that the route is really working!!</h3>
@{{ message }}
<router-link to="/vue"><a>Back to the root</a></router-link>
</template>
<script>
export default {
data () {
return {
message: 'Hoera!!!!'
};
}
};
</script>

Again a very simple component to validate that the route is working.

The next step is that we need to adjust the Laravel routing a little bit. Open the app/Http/routes.php file and add the following lines to your project. This will force Laravel to not reload the application on every route change. Laravel’s routing is now stopped and VueJS can take it over from here.

Route::get('/vue/{vue_capture?}', function () {
return view('vue.index');
})->where('vue_capture', '[\/\w\.-]*');

Next step is to create the landing page from which all VueJS components will be served. You can create something called resources/views/vue/index.blade.php

<!-- /resources/views/vue/index.blade.php -->
@extends('layouts.app')
@section('content')<h1>This is a vue component</h1>
<div id="app">
<router-view></router-view>
</div>
<script src="/js/vue-app.js"></script>
@endsection

I’m including here my layouts.app, which has the navbar and all the other related things. Within the content we load the Vue JS component and also show the router-view.

We’re almost there. Last step is that we need to configure the webpack configuration. We will be using Laravel Mix for the deployment. Make sure the following file is present: webpack.mix.js

It should have the following content:

let mix = require('laravel-mix');
mix.js('resources/assets/js/vue-app.js', 'public/js');

This will call laravel-mix, compile the vue-app.js and deploy it in the public/js file.

Now we’re all set. Let’s do the deployment:

npm run production

If the deployment went fine, you should be able to see a file in the public/js folder. Now open your application and browse to the http://localhost/vue. Localhost of course can be different, depending on how your environment is configured. If everything went well you should be able to see that the VueJS is loaded. When you use the url to the example component, the Example component should load. The nice part here is that page isn’t refreshed! So if your intention is to build a single page application with different components using the vue-router it all can work together as long you stay within the vue subdirectory. Using another subdirectory might refresh the page and all the components to be loaded again. If you don’t want this, make sure the routes.php file is configured properly.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store