Structuring Vue 2, Vue Router, Vuex for a Single Page Application

Part 5 of 48 in API Driven Development With Laravel and VueJS
Dan Pastori avatar
Dan Pastori October 2nd, 2017
⚡️ Updated content is available We learned a lot since we originally wrote this article. We now have this updated for Laravel 10, Vue 3/NuxtJS 3, and Capacitor 3.

As of right now we have the scaffolding up for a single page application. We’ve installed Laravel, configured social logins with Socialite, configured our own oAuth server with Laravel Passport and configured SASS and JS.

Now we will start working with the Vue JS eco system (Vue2 + Vuex + Vue Router). In my opinion, this eco system is the most thoroughly thought out, easy to implement, functional Javascript front end framework available. It’s so easy to use, and pick up especially with the clear documentation provided by Vue JS (Introduction — Vue.js) and Jeffery Way’s video tutorial series on how to use VueJS ( Learn Vue 2: Step By Step ). If you want to learn Vue in a weekend it’s totally possible with Jeffery’s series.

Remember, as we develop our coffee finding application you can follow along here: GitHub – serversideup/roastandbrew.

The Power of Vue 2, Vue Router and Vuex

When combined together there is little more you need to do to make a single page app. Vue 2 handles all of the reactive design and the building of Web Components. If you haven’t used Web Components before, you are in for a treat! They store the HTML, Javascript, and CSS in one simple to use template! It makes them easily re-usable.

Vue Router works natively with Vue 2 and provides a routing component that utilizes the HTML 5 History API to make linkable pages in your app but do it in a single page app manner. The documentation can be found here: Introduction · vue-router if interested. I’d say this is more of the front end core of our Single Page App since it really ties it all together.

Vuex is a state management system for handling your single page app’s data. It stores all of the data used by your app in a single source of truth. This is extremely helpful for dealing with a large single page application. If you’ve used components and modules before and you haven’t used a single source of truth, you know you will be passing lots of properties back and forth to keep the data in sync. This becomes very cumbersome very quickly. With Vuex, you can import certain modules into your components and those components can access the data. You make changes to the by calling actions which perform mutations. This way all changes can be tracked and everything is kept in sync. If you read their introduction here: What is Vuex? · Vuex there are some beautiful diagrams on how it all works together. The best example of how to figure out if you need Vuex or not is in their docs “Flux libraries are like glasses: you’ll know when you need them.”

To cap it all off, Vue comes with development tools for both Firefox and Chrome and they can be found here: GitHub – vuejs/vue-devtools: Chrome devtools extension for debugging Vue.js applications.. You can see the current state of the application as well as the data in the components, route information, and event tracking all within your development tools on either Chrome or Firefox. I work with Chrome and I use this inspector window 99% of the time when working with Vue. It’s extremely helpful and really ties everything together.

Step 1: Let’s Get Rolling! Re-configuring Vue

In the last tutorial where we set up our SASS and JS, we actually removed the reference to Vue in our /resources/assets/js/app.js file. Let’s re add it. We don’t need to install anything since we already in our package, and we will finally be running npm install as well in our app!

First open up /resources/assets/js/app.js and add the following line right below the axios token configuration:

import Vue                from 'vue'

Next remove:

const app = new Vue({
    el: '#app'

We will be re structuring that statement after we install Vue Router and Vuex.

Our /resources/assets/js/app.js file should now look like:

window._ = require('lodash');

try {
    window.$ = window.jQuery = require('jquery');

} catch (e) {}

 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

 * Next we will register the CSRF Token as a common header with Axios so that
 * all outgoing HTTP requests automatically have it attached. This is just
 * a simple convenience so we don't have to attach every token manually.

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found:');

import Vue    from 'vue';

If you haven’t installed foundation sites yet, check out this article:

Step 2: Install Vue Router

Vue router is an NPM package so all you have to do is run npm install vue-router —save-dev and you should be good to go!

Step 3: Install Vuex

Like Vue Router, Vuex is simply installed from the command line through NPM. Just run npm install vuex —save-dev and you should be good to go!

Step 4: Configure JS Directories

If you take away anything from this article to use in your own apps, this is what I think is the most important. I also believe this is the most open to critique and improvement.

I’m a huge advocate of app structure for scaling and maintainability. So I like to do this right away before we even write a line of code so we don’t have to do this later on. The folders essentially give us buckets to drop our code into so we know how our app is structured and where to find certain pieces of information.

We set up our SASS structure following the 7-1 pattern Sass Guidelines in the last tutorial That one was outlined pretty clearly.

This structure is what I use for my Single Page Apps. First I create the directory: /resources/assets/js/api. This is where I’ll store all of my API route calls for the front end of my app. I’ll divide them up by resources too. I can already envision a file in this directory called cafe.js where I will retrieve all cafes or add a cafe.

Next I’ll add the /resources/assets/js/components directory. We removed this in the last tutorial since it was easy to get rid of the Example.vue component. Laravel’s default install is NOT for a single page app. It’s for using Vue in part of a non-SPA type structure. I just remove that scaffolding so we can build our own. In this directory we will definitely be adding sub directories to group components and make things easy to find.

Third, I’ll add the /resources/assets/js/mixins directory. VueJS has a feature called mixins which are essentially methods that are used in multiple components. This is extremely convenient. For example, in an app I wrote a timezone converter that was used in multiple components to display the date. I had one method to do the calculation and I included it in all of the components I needed. For more information, check out the Vue docs here: Mixins — Vue.js

Fourth, I’ll add the /resources/assets/js/pages directory. In Vue Router, pages are essentially components, however I like to put them in their own directory since they are “special” components in my mind. I feel it is cleaner and easier to find. Pages also can contain sub-pages so they can contain the <router-view></router-view> component which we sill discuss later as we continue to build our app.

Lastly, I’ll add the /resources/assets/js/modules directory. This will be our data stores. Vuex divides our data into modules which we will store in this directory. If you used Vuex in the past, the documentation mentioned splitting the actions, mutations, and getters into separate directories. In Vue 2, these are all merged into a single module. I’d image we’d have a roasters.js file in this directory which would contain all of our information for our roasters data.

We’ve now set up our directories for what we need. We will next create our files that will structure our JS side of the app.

Step 5: Create JS Files

There are a few files that we need to create to divide up our app’s functionality.

First, we create /resources/assets/js/config.js We can store any of our configuration in that file. I use this file to store API URLs based on the environment. So in production, it references the production URL, in staging it references the staging URL and in development it references the dev URL. We will work more in this file as we develop our app, it’s just nice to have that location created before we start our app.

Next, we create an event bus: /resources/assets/js/event-bus.js. What this does it allows for any communication through messaging between components. In Vue 1.x this was handled through broadcasting and dispatching. You can still do emit functionality, but it’s recommended to do this in an event bus: Migration from Vue 1.x — Vue.js We will use this later on in our app, but it’s good to have created. For now add the following code to the file:

import Vue from 'vue';
export const EventBus = new Vue();

This just adds a Vue instance that will be used for message passing.

Third, we will create /resources/assets/js/routes.js. This will contain all of the routes for our single page app on the front end. It just simply defines the routes used by Vue Router. We will shell this out as we build the app, but once again it’s nice to have that location created before building the app. I like to have my buckets available to me right away!

Lastly, we will create /resources/assets/js/store.js. This will be the starting point for all of our Vuex Modules. So Vuex is structured by having one module and then sub modules. This file will contain the parent module and we will import all of the submodules in this file. For now we will leave this blank as well since we will be adding content as we build the app.

We now have all of the scaffolding set up for our Single Page App and the files to house the functionality. Next we need to go back to our /resources/assets/js/app.js file and get everything working!

Step 6: Set Up VueJS

So now at the end of our /resources/assets/js/app.js file we need to add the following code:

new Vue().$mount(‘#app’);

This will set up Vue JS to mount our element with the ID of app. It will also prepare VueJS to use our Vue Router and Vuex store when ready.

Step 7: Run ’npm install’

Now that we have everything set up, we can run npm install to install all of our development dependencies. You could have ran this at any point during building this tutorial, but I just wanted to make sure we have this run otherwise nothing will work.

Step 8: Build App

You can now build your app! To build on development run npm run dev. Your app should build and you can log in and view the blank screen! However we now have more of the scaffolding ready to rock and roll for our Single Page App!

In the next tutorial we will begin configuring Vue Router so we can add some routes to our app! I promise, some actual functionality will be coming soon!

Keep Reading
View the course View the Course API Driven Development With Laravel and VueJS
Up Next → Configuring Vue Router for a Single Page App

Support future content

The Ultimate Guide to Building APIs and Single-Page Applications with Laravel + VueJS + Capacitor book cover.

Psst... any earnings that we make off of our book is being reinvested to bringing you more content. If you like what you read, consider getting our book or get sweet perks by becoming a sponsor.

Written By Dan

Dan Pastori avatar Dan Pastori

Builder, creator, and maker. Dan Pastori is a Laravel certified developer with over 10 years experience in full stack development. When you aren't finding Dan exploring new techniques in programming, catch him at the beach or hiking in the National Parks.

Like this? Subscribe

We're privacy advocates. We will never spam you and we only want to send you emails that you actually want to receive. One-click unsubscribes are instantly honored.