SPA with Vue.js and Laravel: Setting Things up

SPA with Vue.js and Laravel: Setting Things up

As with all projects, we start by setting things up. We'll scaffold a new Laravel project, configure Elixir, prepare our Laravel's main view, and create our very first Vue page component.

Please note that since this series is based on Vue 1.0, we will need to specify each library’s version explicitly — as you’ll see later.

We've got lots of things to do, so let's dive in.

Installing Laravel

Our very first step would be, of course, to install Laravel. I'm using here the laravel-installer tool.

laravel new spa-forum

The next thing is to install all NPM dependences, but before we do so, we have to change the version of laravel-elixir so it can work with Vue 1.0 stuff.

So, in package.json, replace laravel-elixir version with ^5.0.0.

Now we can run:

npm install

Configuring Elixir

In this series, we'll use Vueify for compiling *.vue files. This will allow us to write components in this format:

<template>
  // Your HTML
</template>

<script>
  // Your JavaScript
</script>

<style>
  // Your stylings
</style>

As you can see, in this way we can put all component's related code in a single file — which is pretty cool!

Vueify is specifically for Browserify (which we'll use). If you instead prefer to use Webpack, there's also vue-loader which does the same thing.

Installing Vueify is a cinch with Laravel Elixir. All you have to do is install this package.

npm install laravel-elixir-vueify@1 --save-dev

Then, in your gulpfile.js include it at the top like this.

require('laravel-elixir-vueify');

Since this is a Browserify transformer, everything will automatically work when you call the mix.browserify.

elixir(function(mix) {
  mix.browserify('main.js');
});

Main.js is our application's entry file, which we don't have yet.

The only reason that will make us touch this file again is to mix some external styles. So while we're still at it, let's install the popular Normalize.css package with NPM.

npm install normalize.css --save

Then mix it into our styles for later use.

elixir(function(mix) {
  mix.browserify('main.js')
    .styles([
      './node_modules/normalize.css/normalize.css'
    ]);
});

Organizing Vue files

All of our Vue files will be in our resources/assets/js/ — This is the directory where the majority of our time will be spent.

For the whole project we'll only need three directories and one entry file — main.js.

So, create these three directories: components, filters, services. And don't forget main.js.

In the end, you should have this:

.
├── components
├── filters
├── services
└── main.js

3 directories, 1 file

Our very first page component

Pages in Vue are components. Each component contains everything it needs — HTML (template), CSS, and JS. The router is what we use to determine which component should be shown to the user.

So, this means we need to install the vue-router, and, of course, Vue itself.

npm install vue@1 vue-router@0.7 --save

Now, let's jump to main.js (our application's entry point) and put in the following.

import Vue from 'vue';
import Router from 'vue-router';
import App from './components/App.vue';

// Install the router
Vue.use(Router);

var router = new Router();

router.start(App, '#app');

Okay, let's break this code into three sections.

First, at the top, we imported vue, vue-router, and App (which we haven't created yet).

Then, we installed the router and instantiated a new instance of it.

Lastly, we started the router and we gave it the main application's component (App) and the selector of the element we want to bind that App component to.

All of this means, we have to create two things, the App component and the <div id="app"></div>.

For the App component, create components/App.vue and put in it something like this.

<template>
  Hello from the App component.
</template>

Now, the remaining thing to do is to create that #app element. We'll do that in our main blade view.

While Laravel gives us welcome.blade.php out of the box, I like to rename it to something more meaningful like index.blade.php.

After you do that, replace the content with this.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>SPA-FORUM</title>
  <link href="https://fonts.googleapis.com/css?family=Lato:100,200,300,400" rel="stylesheet" type="text/css">
  <link href='https://fonts.googleapis.com/css?family=Roboto:400,500,700' rel='stylesheet' type='text/css'>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link href="/css/all.css" rel='stylesheet' type='text/css'>
</head>
<body>

  <div id="app"></div>
  
  <script src="/js/main.js"></script>
</body>
</html>

And don't forget to change routes.php accordingly.

Route::get('/', function () {
    return view('index');
});

Finally, run gulp watch in one tab and the server in another tab.

gulp && gulp watch
php artisan serve

Open up the browser and go to http://localhost:8000. You should see this.

First page component

One last thing before we finish up this part. For me, I like to treat the main App component as a component. Which means instead of putting <div id="app"></div> in index.blade.php, I like to put <app></app>. For that to work, you have to change the element selector in your main.js accordingly.

router.start(App, 'app');

What's next?

That's great! We have accomplished many things in this part. By now, you should have some basic sense of how our workflow will be. Don't worry if some things are not clear at the moment; we still have many things to cover, and we'll get into more details in future parts.

Our next part will focus on the routing aspect of our application. We'll learn how to define some routes and how to navigate between them. We'll also see how Laravel's routing file should look like.

Vue Laravel
Taha Shashtari

About Taha Shashtari

I'm a freelance web developer. Laravel & VueJS are my main tools these days and I love building stuff using them. I write constantly on this blog to share my knowledge and thoughts on things related to web development... Let's be friends on twitter.