Weekend Project (Part 3): Scaffolding a Vue App with vue-cli and Managing State with Vuex

Josh Porter
Hacker Valley Studio
7 min readJan 22, 2018

If you’re just now tuning in, be sure to read Part 1 and Part 2.

Vuex Data Flow. Source: https://vuex.vuejs.org/en/intro.html

Everyone keeps talking about all of these Javascript frameworks lately — Angular, React, Vue… there are just too many options. Taking on this project, I decided to just pick one and roll with it. I initially heard about Vue.js on the Does Not Compute podcast. The hosts, Paul Straw and Sean Washington, spoke highly of it, so I decided to check it out. I’ve looked into Angular and React before (having done some React work recently) and after minutes of reading the Vue documentation and examples, I fell in love. It’s simple, clean, and has a very gentle learning curve, with being rather performant being a nice bonus.

There are multiple ways to write Vue code, including traditional Javascript files (.js) using ECMAScript 5(ES5). The path we’ll take in this post is my personal favorite, writing Vue templates (.vue) using ECMAScript6 (ES6). This method allows us to write our components as individual files consisting of three core components — template, script, and style — and provides us with a file encapsulating everything our component needs.

Prep Work

Before we dive into writing some code, there’s a few things to install… Please follow the install notes for each of these tools before proceeding.

  • Node/NPM (I like to use nvm to install Node and NPM)
  • vue-cli*
  • The websocket server from Part 2 of this blog

Edit: This post is using vue-cli 2.5.16. I’d now recommend using @vue/cli 3.0 beta. It’s greatly improved and makes the cli a very powerful tool.

Getting Started

Edit (03/27/2019): The Vue ecosystem is always changing, and vue-cli 3 is very intuitive and brings so many great new features to initializing a Vue project. I recommend checking out the docs here.

To get our project rolling, the quickest and easiest way is to use vue-cli, which scaffolds a project for us to include a “hello world” vue project using one of many prebuilt templates. I’m a fan of webpack, so we’ll use the vue-cli webpack template.

In your terminal, run the following command:

$ vue init webpack [project-name]

This command will walk you through a few questions about your project. You can usually use the defaults, but for the sake of brevity we’ll answer “N” to a few questions — Use ESLint, unit tests, and e2e tests. I typically recommend using these, but for this tutorial we won’t need them.

Vue CLI Scaffold

Scaffolded Vue with Webpack

Taking a look at the output of the scaffold, we see that it created the package.json for NPM, the bulky node_modules folder, an index.html, and a bunch of other folders. Let’s go over the folders it created:

  • build — This contains a build script and a modularized webpack config, we can leave this as-is for now.
  • config — More webpack config templates for different build environments.
  • src — This is where our front-end Vue.js code will go. It contains a couple of subdirectories for storing aspects of the Vue ecosystem, such as components, routes, and additional assets.
  • static — A folder to store static assets, such as images and font files.

Without touching any of the code, we can start the Vue app using the webpack dev server by running the following command.

npm run dev

This starts a hot-reloading development server at http://localhost:8080.

vue-cli “Hello World”

The command we just ran isn’t some sort of magic, it’s a script predefined by vue-cli in the package.json. NPM allows us to write scripts, or tasks, to run for assigned commands. The dev command simply runs our webpack dev server. The other command we’ll be concerned with is the build command, which compiles our front-end code using webpack into a designated directory.

Vue Basics

Now that we have some scaffolded Vue code, we’re ready to start creating our own components and building out our app. Rather than boring you with a Vue how-to, I highly recommend checking out Vue’s official guide to get spun-up on the basics of the framework. From personal experience, I found Vue had a very small learning curve and their guide was comprehensible and easy to digest. Their documentation is world-class and some of the most comprehensive docs I’ve dealt with.

Once you’re rock solid with the Vue fundamentals, we can tackle some of the more complex aspects of the framework and its ecosystem. These additional modules will greatly enhance the capabilities of your project, such as providing client-side routing and centralized state management for larger projects.

Centralized State Management with Vuex

When working with a complex Vue application with multiple components, it is rather common for components to have a need to share data. Without Vuex, we would have to pass data down as props, which are immutable by the child component. To alter the data on the parent component, we’d have to $emit an event containing the updated data, as well as handle the event from the parent. With a small application where we need to do this once or twice, that’s fine. But with a larger application this gets messy real fast. It’s okay though, Vuex is here to help you out!

Shared State with Vuex

Shared state sounds simple, the pieces of your application that are needed globally are all stored in one location, almost like having a global variable. However, it’s not as simple as this. Vuex consists of four core components:

  • State — the single source of truth for our application’s state. State is immutable.
  • Getters — computed state based on store state. Similar to computed props.
  • Mutations — the only true way to alter state. Mutations cannot be called directly, but must by activated by calling store.commit([mutation]). Mutations must be synchronous.
  • Actions — similar to mutations, except actions commit mutations and can contain asynchronous operations.
Vuex diagram. Source: https://github.com/vuejs/vuex

For more technical details on the various aspects of the Vuex state management architecture, refer to their official documentation.

Creating the Store

The creation of the store is relatively simple now that you understand the core concepts of the store. Rather than trying to explain Vuex using the actual codenames game code, we will create a basic store that will manage a counter. This is much more comprehensive and allows me to cover more aspects of Vuex.

Simple Vuex store for incrementing and resetting a counter.

After creating the store, we want to tell Vue to use it for its state management. This is achieved by simply importing the store and adding it to the main Vue instance, the same way you’d integrate the Vue router.

Adding the Vuex store to our main Vue instance.

Using Vuex Within Components

Now that our store is configured, we’ll want to use this within a Vue component to increment and reset the counter. To do so, we can simply access our global store from the variable this.$store. However, this can become unwieldy when attempting to access multiple aspects of our Vuex instance. Luckily, Vuex provides some helper methods for attaching pieces from the Vuex store to our components. This allows us to access our count by using this.count rather than this.$store.state.count. Additionally, it allows us to only attach the pieces from our store that the specific component requires. Each Vuex piece has a helper, as described below, and are each commonly used with the “spread” operator ... which explodes the object that gets returned, allowing us to essentially merge it with our existing object without any additional libraries or utilities.

  • StatemapState in the compute block of the component.
  • GettersmapGetters in the compute block of the component.
  • MutationsmapMutations in the methods block of the component.
  • ActionsmapActions in the methods block of the component.

Below, let’s compare the Counter component with and without the helpers.

Simple counter component without the mapping helpers.

Take note of the computed and methods blocks of the component. In the above example, we create individual functions that simply return the state, getters, mutations, and actions using the longhand form such as this.$store.state.count. This adds unnecessary bloat to the component.

Simple counter component using Vuex with helpers.

Using the helpers is made incredibly simple with the spread operator, and it allows us to use the Vuex elements in conjunction with our own computed properties and methods, as shown above. We can import the doubleup getter while also creating our own custom property, halfCount.

Conclusion

Vuex is a very useful and powerful component of the Vue ecosystem, and is very simple to integrate into applications of any size. However, each use case is different and not all applications require the additional overhead and complexity. Take this knowledge with you and use it on your next project to avoid ending up with prop passing spaghetti. Stay tuned for the next segment on integrating Socket.io into the Vuex store!

Update 2018/04/24 — Learn how to integrate websockets into your project using Socket.IO and Vuex in Part 4 of this series!

Support Us

  • Give this post some claps 👏👏👏👏
  • Give this post some feedback in the comments
  • Join our Slack channel
  • Follow us on Facebook, Twitter, Reddit

--

--

Josh Porter
Hacker Valley Studio

Baltimore-based software developer with a passion for clean code, craft beer, and video games. http://codecaffeinated.com