Vue.js — Project setup

Getting started with Vue, Webpack and Bulma

Matt Bradford
WDstack

--

Recently I had a chance to play around with the Vue.js framework. I have been very impressed with how easy it is to get up and running. One of the best parts about Vue is that it is light weight and easy to setup, plus it can be used to bridge the gap with web apps built in older technologies (more on this in a future post). In this post I want to outline the steps I took for getting a new project off the ground with Vue. If you want to jump straight to the finished repo, check it our here.

Here is what I will cover:

  • Creating project with vue-cli
  • Project structure
  • Adding Bulma for layout
  • Setting up the vue-router
  • Setting up vue-resource
  • ***Setting up axios [alternative to vue-resource]

Creating project with vue-cli

The easiest way to get up and running with Vue is via the vue-cli. Check out the official docs here. There are a handful of templates that will get you going, I started with the webpack template.

**Make sure you have a current version node setup on your system

$ npm install -g vue-cli
$ vue init webpack vuesetup

The vue-cli will ask a series of questions that will aid in setting up the configuration of the project. Once it completes, it’s time to install the dependencies. I prefer to use yarn, but you can also use npm install.

$ cd vuesetup
$ yarn
OR$ cd vuesetup
$ npm install

Once the dependencies are installed, run the following to launch the base application.

$ yarn run devOR$ npm run dev

Once you open up the project in your editor, you can see all the work the cli did for you. It setup a basic app with webpack, hot-reload, lint-on-save, unit tests and several other features … kudos to the vue-cli team! For more details on what’s included and how it all works, check out the webpack plugin documentation here.

Project Structure

Quick note on project structure. Everyone has their own flavor of how they like to organize their projects. I tend to keep related items close to each other. I altered the setup from the cli inside the /src folder (above that I left everything just as the cli created it).

Main item to note is that the containers will be the base pages of the application [Home / Dashboard / Projects / Login ] and the components for these containers will live the in the components folder. For larger projects, the I like to create folders inside the components directory to organize related components together.

Adding Bulma

Bulma is a css framework that I have been using lately, it is very light weight and does not have any JS associated with it directly. Obviously you can use whatever css framework you like(or none at all), but I like bulma because it uses flexbox for layout (also it has several components and good documentation).

In the index.html file, link to bulma via the cdn:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.3/css/bulma.min.css" />
index.html

** I also link to font awesome for icons

Using the bulma nav classes, let’s create a navbar component.

<template lang="html">
<nav class="nav has-shadow" >
<div class="nav-left">
<a class="nav-item is-brand" to="/">
Vue Project
</a>
<a class="nav-item is-tab" to="/dashboard">
<i class="fa fa-dashboard"></i> Dashboard
</a>
<a class="nav-item is-tab" to="/projects">
<i class="fa fa-list-alt"></i> Project List
</a>
</div>
<div class="nav-right">
<span class="nav-item">
<a class="button">Logout</a>
</span>
</div>
</nav>
</template>
<script>
export default {
name: 'navbar'
}
</script>

This will create a simple navbar for our application

I have also made a some adjustments to the main.js file to mount the application. Set the template in-line and imported the navbar.

import Vue from 'vue'
import navbar from './components/navbar'
/* eslint-disable no-new */
new Vue({
template: `
<div>
<navbar />
<section class="section">
<div class="container is-fluid">
</div>
</section>
</div>
`,
components: {
navbar
}
}).$mount('#app')

Setting up vue-router

Now that we have our basic layout setup, let’s add the vue-router to our app and wire up our pages. Go back to the shell and add vue-router:

$ yarn add vue-routerOR$ npm install vue-router --save

Once it completes add a new file in the root of /src named router.js. This is where we will setup our router and store our application routes.

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)import home from './containers/Home'
import dashboard from './containers/dashboard'
import projects from './containers/projects'
// application routes
const routes = [
{ path: '/', component: home },
{ path: '/dashboard', component: dashboard },
{ path: '/projects', component: projects }
]
// export router instance
export default new Router({
mode: 'history',
routes,
linkActiveClass: 'is-active'
})

Notice where I export the router, I set the mode equal to history. This removes the hash from the url and gives the app a cleaner url string. One other item is the linkActiveClass, this tells the vue-router what class to add to the navigation to make the menu item active (will vary based on what css framework you choose).

Back in the navbar component, adjust the <a> tags to <router-link> tags. These tags will render an <a> tag but will be tied to the router to apply the correct active class.

<template lang="html">
<nav class="nav has-shadow" >
<div class="nav-left">
<router-link class="nav-item is-brand" to="/">
Vue Project
</router-link>
<router-link class="nav-item is-tab" to="/dashboard">
<i class="fa fa-dashboard"></i> Dashboard
</router-link>
<router-link class="nav-item is-tab" to="/projects">
<i class="fa fa-list-alt"></i> Project List
</router-link>
</div>
<div class="nav-right">
<span class="nav-item">
<a class="button">Logout</a>
</span>
</div>
</nav>
</template>
<script>
export default {
name: 'navbar'
}
</script>

Next, let’s create the home, dashboard and project components that our router will load as we navigate.

<!-- home page -->
<template lang="html">
<div id="home">
Home content will go here
</div>
</template>
<script>
export default {
name: 'home'
}
</script>
<!-- dashboard -->
<template lang="html">
<div id="dashboard">
Dashboard content will go here
</div>
</template>
<script>
export default {
name: 'dashboard'
}
</script>
<!-- projects -->
<template lang="html">
<div id="projects">
Project content will go here
</div>
</template>
<script>
export default {
name: 'projects'
}
</script>

Finally, update the main.js file and let the root Vue instance know about the new router. Also notice I added the <router-view> component to the template. This is the location where the router will place our selected routes.

import Vue from 'vue'
import navbar from './components/navbar'
import router from './router'
/* eslint-disable no-new */
new Vue({
template: `
<div>
<navbar />
<section class="section">
<div class="container is-fluid">
<router-view></router-view>
</div>
</section>
</div>
`,
router,
components: {
navbar
}
}).$mount('#app')
view of router in action

Setting up vue-resource

Now that we have our router up and running, let’s setup vue-resource to make api calls in our app. Head back to the shell and install vue-resource

$ yarn add vue-resourceOR $ npm install vue-resource --save

Next, open the routes.js file and import vue-resource and tell the Vue instance to use it

import Resource from 'vue-resource'Vue.use(Resource)

Once this is set, you will be able to access the http resource in your Vue components via this.$http. For more details, check out the documentation for vue-resource here. To demonstrate how this will work, let’s make a call using a mock backend (mocky.io) and list some projects on our project page.

<template lang="html">
<div id="projects">
<div class="columns">
<div class="column is-half">
<div class="notification">
List of fake projects, courtesy of mocky.io ...
</div>
<div class="">
<table class="table">
<thead>
<tr>
<th>Project Name</th>
<th>Assigned To</th>
<th>Priority</th>
</tr>
</thead>
<tbody>
<tr v-for="item in projects">
<td>{{item.name}}</td>
<td>{{item.assignedTo}}</td>
<td>{{item.priority}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'projects',
data: function () {
return {
projects: []
}
},
methods: {
loadProjects: function () {
this.$http.get('http://www.mocky.io/v2/585e03ce100000b82c501e8e').then((response) => {
// depending on your api, you may or may not have to make the .json() call
// if your repsonse.body is null, try this
response.json()
this.projects = response.body
}, (err) => {
console.log(err)
})
}
},
mounted: function () {
this.loadProjects()
}
}
</script>

I created a placeholder in the data section and setup a method to call the api. Once the promise returns it sets the data object and our screen is loaded. I initiate the call once the component has mounted.

Setting up axios

As an alternative to vue-resouce, you can use axios if you like. Since vue-resource is getting moved out the of the official vue organization (more details here) I thought I would provide an alternative. To get started, install axios:

$ yarn add axiosOR $npm install axios --save

Unlike vue-resource, you do not need to call Vue.use() since this library is not directly integrated with Vue. If you want to use to axios similar to vue-resouce, check out vue-axios. This is one way to add axios to the Vue object. For our simple app I am just going to axios directly. In the Projects.vue component I adjusted the load method as follows:

methods: {
loadProjects: function () {
axios.get('http://www.mocky.io/v2/585e03ce100000b82c501e8e').then((response) => {
this.projects = response.data
}, (err) => {
console.log(err)
})
}
}

Conclusion

Now we have a project built that is ready to go with a router and ability to access a backend api. In my next post, I will cover how to setup auth0 with this project and provide client side security. You can find that post here.

--

--