The Vuex Tradeoff

Vue developers: want to up your programming output? Start with automating Vuex boilerplate code.

Vuex is a wonderful tool for managing state in Vue applications. Unfortunately, it requires a great deal of boilerplate code. What was once a single method is now three mutations and an action spread across three files. Yes, you’re investing time into your code now that will pay dividends later. It would be nice, however, to automate some of that boilerplate…

Hygen

Automating Vuex boilerplate with Hygen

 Hygen, a tool for code generation, does just that. It offers a few features on top of your typical code gen library.

A template is a Hygen file containing boilerplate code, and instructions on where to inject it. A command executes code generation.

  • - You commit your templates to version control, so anyone working on the same repo benefits.
  • - Hygen uses an intuitive file structure for declaring the code you’d like generated. It includes a header section for articulating how (and where) the code will get copied, and a body section for the code itself. Furthermore, it comes with a syntax for variable content.
  • - You can easily chain together templates, causing multiple injections to occur with a single command.

Integrating Vuex with Hygen

There are a number of Hygen examples on the web. The Hygen docs even walk through setup for a React / Redux application. However, resources for integrating with Vuex are tough to find. The very popular Vue Enterprise Boilerplate project uses code gen as well, but in a more surface-level way.

Vuex poses a couple of challenges. For example, the lion’s share of our Vuex actions involve three mutations: one for the start of an asynchronous action, one upon successful completion, and one upon failure. So adding an async action means:

1.) Declare an action in actions.types.js

2.) Declare three mutations in mutations.types.js

3.) Import the action and mutations into a Vuex Module

4.) Implement the async code, committing mutations at the appropriate times

Here's what that would look like in code:
// actions.types.js
export const FETCH_DATA = "FETCH DATA";
// mutations.types.js
export const FETCH_DATA_START = "FETCH DATA START";
export const FETCH_DATA_SUCCESS = "FETCH DATA SUCCESS";
export const FETCH_DATA_FAILURE = "FETCH DATA FAILURE";
// Example module
import api from "./api";
import { FETCH_DATA } from "./actions.types.js";

import {
  FETCH_DATA_START,
  FETCH_DATA_SUCCESS,
  FETCH_DATA_FAILURE,
} from "./mutations.types.js";
const initialState = () => ({});

const getters = {};

const mutations = {
  [FETCH_DATA_START](state) {},
  [FETCH_DATA_SUCCESS](state) {},
  [FETCH_DATA_FAILURE](state) {},
};

const actions = {
  [FETCH_DATA]({ commit }) {
    commit(FETCH_DATA_START);
    return api
      .get("/data")
      .then((resp) => {
        commit(FETCH_DATA_SUCCESS, resp);
      })
      .catch((err) => {
        commit(FETCH_DATA_FAILURE);
        throw err;
      });
  },
};

export default {
  getters,
  mutations,
  actions,
  state: initialState,
};

If the module doesn’t exist yet,  add another two steps: creating the module, and importing it into the Vuex root (index) file.

Automating Vuex with Hygen

Now, you may complete the entire process with a few commands. This repository includes the tools you need.

Make sure to install Hygen and clone this directory:

npm i -g hygen
# Or yarn global add hygen


git clone https://github.com/koptionalsoftware/vuex-hygen-templates.git
cd vuex-hygen-templates

And then you can instantly generate actions, mutations, and modules:

#create an action and some mutations. Use camelCasing for the action!
hygen asyncaction new fetchData

## The above is equivalent to:
# hygen action new fetchData
# hygen mutation new fetchDataStart
# hygen mutation new fetchDataSuccess
# hygen mutation new fetchDataFailure


#create a module
#   users = the name of the module directory
hygen vuexmodule new --module=users

#inject the actions / mutations into the module
#  The  module and actions / mutations must exist first! ( see previous steps )
hygen vuexactions new fetchData --module=users

The README includes steps to integrate these commands into a current project as well.

A Quick Demo

Things to Keep in Mind

These Hygen templates are a bit opinionated.

Devs opt for different styles when writing actions; I use underscore, all-caps casing.
// What I do
export const FETCH_DATA = "FETCH DATA";

// Things other people sometimes do
export const fetchData = "fetchData";
export const fetchData = "FETCH_DATA";
export const fetchData = "FETCH DATA";

// and about every combination of camel / underscore casing

I’ve also seen programmers structure their Vuex code differently. For instance, Ducks proposes more of a modular style. Other people throw all action code in one file.  In any case, adapting the code to these styles is pretty trivial.

Even excluding style though, sometimes three mutations are not needed for an action. For instance, you may sometimes use a "finish" mutation instead of the "error" and "success" combo. Occasionally, you’ll commit a mutation from a Vue template rather than from an action. In these cases, you can lean on the stand-alone action / mutation generators. That means a bit more manual work, though.

Finally, the action injection command offers room for improvement. As noted, it relies on code comments as entry points. Using an auto formatter can sometimes strip these comments away.

In any event, we’ve discovered that automating Vuex boilerplate saves hours of time, and makes Vue development more enjoyable.