It seems a bit silly to be writing a blog about vue.js on WordPress (Sorry WordPress, I think you’re great!). I mean, surely I can design my own site!? So, I thought it would be a good idea to start by going through a project to design the website for this blog.

I know. Blogs are so cliché when it comes to learning web development frameworks, but actually, we are going to create a real blog; to really be used in the wild, and that’s a bit different, because once completed all these blog posts will be migrated to the website we build here, and that site will really have to work!

Along the way I also hope to post other non-project related blog posts to focus on particular aspects of Vue, but for now let’s get started.

For this project, we are going to build a full SPA (Single Page App) using Laravel as our backend. Don’t worry too much though, it’s just feeding us data, which can be done in any language, and using any framework, so just ignore the Laravel specific stuff if you’re using Python, Ruby, .Net or anything else for your backend; the Vue stuff remains the same.

That said, in this particular post, we need to configure laravel for our project, so you may find it a little more Laravel heavy than following posts.

Let’s start by creating a new =Laravel 5.4 project. Assuming we already have everything set up on our machine, lets just fire up a command console,  navigate to our project directory and do:

laravel new vuetiful-blog

Hopefully that installed our laravel project in the directory called “vuetiful-blog”, so we can now navigate to our project directory:

cd vuetiful-blog

If at this stage Laravel hasn’t done it’s thing properly run:

composer install

Now, we need to set up our laravel keys, so:

php artisan key:generate

Now let’s pull in all the stuff we need from npm. If you open package.json, you will see something like this:

"devDependencies": {
  "axios": "^0.15.3",
  "bootstrap-sass": "^3.3.7",
  "jquery": "^3.1.1",
  "laravel-mix": "^0.7.2",
  "lodash": "^4.17.4",
  "vue": "^2.1.10"
}

That’s a bit presumptuous!  There’s some stuff there we don’t really want. For this project I want to use semantic-ui so let’s get rid of bootstrap-sass (if you are just using this as a reference for your own project, then feel free to keep bootstrap if you prefer), we don’t want laravel-mix because that’s a webpack package and we will be using the simpler browserify. We may as well use axios because vue-resource may not be fully supported for much longer and let’s keep lodash and jQuery for now – if we don’t use them then we can remove them later, however, like Bootstrap, Much of semantic-ui is heavily reliant on jQuery so we may need to build some bridge components to accommodate it if we can’t find alternatives. So, our new package.json should be:

"devDependencies": {
  "axios": "^0.15.3",
  "jquery": "^3.1.1",
  "lodash": "^4.17.4",
  "vue": "^2.1.10"
}

That’s cool, but we are building an SPA and our entire app will be made using .vue files and compiled using browserify, so we will need vueify to transform the .vue files we write. We will also want to be using ES2015 (shiny new JavaScript), so let’s pull in babel and the ES2015-preset plugin to transpile our ES2015 code.

Laravel may have dumped gulp in 5.4 in favour of using webpack via laravel-mix, but I don’t want to, so let’s pull in gulp, and of course I want to write my gulpfile in ES2015 aswell so let’s bring in babel-register to help with that. Finally we will need vinyl-source-stream to output our bundled files, so our new package.json looks like:

"devDependencies": {
  "axios": "^0.15.3",
  "babel-core": "^6.22.1",
  "babel-preset-es2015": "^6.22.0",
  "babel-register": "^6.22.0",
  "babelify": "^7.3.0",
  "browserify": "^14.0.0",
  "gulp": "^3.9.1",
  "jquery": "^3.1.1",
  "lodash": "^4.17.0",
  "vinyl-source-stream": "^1.1.0",
  "vue": "^2.1.10",
  "vueify": "^9.4.0"
}

Those dependencies might be out of date by the time you read this, so quickly install npm-check-updates globally with administrator/sudo privileges:

npm install -g npm-check-updates

And run the following in the root of your project:

ncu -u

Now all the dependencies have been updated, let’s install them:
npm install

Setting up Gulp, babel, browserify and vueify

Our first step is to set up gulp to compile our .vue files correctly. The first thing I’m going to do is delete webpack.mix.js and create a new file named gulpfile.babel.js – The addition of babel in the file name will let gulp know we are using ES2015 in the gulpfile itself which will load babel-register so we don’t get compile errors. For now I just want to make sure everything is up and running, so I’m going to make a minimal gulpfile for the project:

import gulp from "gulp";
import browserify from "browserify";
import source from "vinyl-source-stream";

gulp.task('default', () => {
  return browserify({
    entries: './resources/assets/js/app.js',
    debug: true
  })
  .bundle()
  .pipe(source('app.js'))
  .pipe(gulp.dest('./public/js'));
});

We haven’t applied our transforms yet, I prefer to add them into package.json so they are applied automatically any time browserify is used, which may come in handy later, so I’m adding the following to package.json:

"browserify": {
  "transform": [
    "babelify",
    "vueify"
  ]
}

Of course we haven’t set up babel yet, so let’s create a .babelrc file in the root of the project and add the following:

{
  "presets": ["es2015"]
}

That’s gulp, babel, vueify and browserify setup, so we’re good to go!

Setting up Vue

Next we need to set up Vue. Laravel uses a bootstrap.js to add dependencies, but I don’t want to add them until I need them, and for now all I need is Vue, so let’s open up resources/assets/app.js and we get:

require('./bootstrap');

component('example', require('./components/Example.vue'));

const app = new Vue({
  el: '#app'
});

OK,  let’s start by getting rid of require('./bootstrap'); we are just going to import Vue directly, you will also notice that laravel has registered a vue component globally. It also assumes we are using the standalone-build of vue and we are using the runtime-only build because we don’t need the compiler –  vueify will do all that magic for us – so we also need to add a render function and a base component.

Let’s start by creating a base component called App.vue inresource/assets/js/component. We just want to know we are set up so let’s just add the following:

<template>
  <div>
    <h1>Setup Complete</h1>
  </div>
</template>

Now in app.js let’s import Vue and our base component (App.vue) and create a render function so we can mount our base component. We can also get rid of the Example.vue component, so our app.js  ends up with:

import Vue from 'vue';
import App from './components/App.vue'

const app = new Vue({
  render: h => h(App)
}).$mount('#app');

That’s good, now we just need to create an entry point for our app, so in resources/assets/views create a file called app.blade.php and let’s just create a div with the id app so Vue can mount our component:

<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Vuetiful Blog</title>
    </head>
    <body>
      <div id="app"></div>
      <script src="/js/app.js"></script>
  </body>
</html>

And, finally, we need to set up our route in Laravel. Because we’re building an SPA we will be using vue-router for the main web routes (see part 4), so we just need to let Laravel know where to find our main entry point which is app.blade.php, so let’s just add that to our web routes in routes/web.php:

Route::get('/{vue?}', function(){
  return view('app');
})->where('vue', '^(?!.*api).*$[\/\w\.-]*');

This simply tells Laravel to route any requests that aren’t to the api to app.blade.php.  And that’s it, we should be done!

Let’s run gulp to compile the components:

gulp

Now let’s fire up a server, I’m just going to use laravel’s serve to set up my localhost:

php artisan serve

Now lets check the browser at http://localhost:8000:

setup_complete_screengrab

And it all works!

I admit that seems like a bit of a rigmarole to set up, but it should be smooth(ish) sailing from here.

In part 2, we will be setting up Semantic-UI for use in this project.

If you want to skip setting up Semantic-ui, then jump to part 3 to configure Hot-Reloading and then in part 4 we finish the setup by adding vue-loader.

Advertisements