My Vue Experience after 3 projects in 18 months

My Vue Experience after 3 projects in 18 months

Hello developer pal!, glad to see you here.

In this post, I'll share my experience after 3 projects written/maintained in Vue 2.* during the last 18 months.

Show Me The Topics

The topics to be focused on are:

  1. Agile Methodology and frameworks used
  2. Design Systems
  3. Infrastructure
  4. Backend
  5. State Management
  6. Frontend

Disclaimer: This post comes from my own experience during this lapse, not saying this is the best way to go, nor the worst, any contribution is more than welcome in the threads below!

Agile Methodology and Frameworks used

Are you familiar with Agile Software Development?, cause I really am right now!, I really like this simple sentence as a summary:

Agile is the ability to create and respond to change. It is a way of dealing with, and ultimately succeeding in, an uncertain and turbulent environment.

Nice, simple, straight to the point, isn't it?, during the last year and a half my teams passed over 3 different of its frameworks:

  • Scrum: from my perspective, the most interesting, this framework allowed our cross functional team to interact as a whole, splitting the work up in 2-weeks sprints, and constantly adjusting the business requirements, it is a quite nice experience!, highly recommended.

  • Kanban: my second favorite from top to bottom, a good option when the work to be done does not follow the same path, for instance working on different repos at the same time(MonoRepos, MFEs, Legacy Systems)l; when this happens perhaps Scrum is not enough cause the time-frames.

  • Extreme Programming (XP): required for an MVP one of my teams had, from my experience, the most risky one since you dynamically change requirements and some heavy lifting could magically appear/disappear down the road, highly not-recommended unless it is "Extreme"-ly necessary(pun intended), and please be "Extreme"-ly cautious(pun intended X2).

In case you want to read about the Agile Manifesto(the corner stone of the methodology) you can do it right here.

Design System

I learned that after defining the Methodology, it is good to have a robust Design System, you have 2 options: reuse an existing one or create one custom from scratch, either way the benefits are amazing!, when present it covers up 3 different areas:

  1. UI/UX does not repeat itself
  2. WebDev has one-and-only-one source of truth
  3. QA can evacuate questions on its own

In case you want to have some existing guide lines, here you can find a list of available resources on the wild.

In the teams I was working on, those where custom, a recipe for success was:

A great strategy that we found was to create Vue components using Tailwind and creating its respectives stories on Storybook; I can say this is a great approach cause you can define your Design System in Storybook itself, and publish this to an accessible page for all your team members(under a VPN is even more secure), so it is available for everybody, they can see the components running in an isolated scope before even implementing it!

Infrastructure

Oh right, we had the Methodology and the Design System then what?

I learned that here it comes the Infrastructure, well the approaches we had the opportunity to work with where Jenkins, TravisCI and GitHub Actions.

For experience, in big projects, Jenkins is a great way to go, among all its pros, you can set it up for running on your behalf the unit testing and end-to-end testing before deploying!, in case of failure you are notified and a fix can be included.

In small projects, or side projects, you can use the TravisCI + GitHub Actions approach; GitHub already has some built-in options for setting up ymls and help you with Merge Requests and Deployments.

Note: TravisCI gives you 10,000 builds for free with your sign up, for small projects, proof of concepts or side projects it is a great deal!.

Backend

Also I learned for these projects, that a Backend on NodeJS and Firebase is easily handle.

I wrote non-canonical series related to some Firebase features if you want to check them.

State Management

I learned about VueJS + Vuex. I'm used to Rxjs, NgRx but Vuex is from my experience the easiest; with a little of knowledge you are able to start creating on your own, the separation of concerns through modules, and the way to reference then is crystal clear:

store/
   ├── index.js
   └── modules/
       ├── module1.store.js
       ├── module2.store.js
       ├── module3.store.js
       ├── module4.store.js
       └── module5.store.js

Referencing the modules in the index.js make them importable through out your project, this includes State, Getters, Mutations, Actions; a new module is just the addition of a new entry in the index.js, a deprecated module is the removal of that entry(conditions may apply).

I also learned that you can namespace the modules!, then you can differentiate the elements by module instead of having dozens of lines with no context(trust me, with several modules this is amazing for debugging purposes, scalability and visual sake).

A clear example can be found below:

import { mapState, mapGetters, mapActions, mapMutations } from 'vuex';

export default {
  computed: {
    // Accessing root properties
    ...mapState('my_module', ['property']),
    // Accessing getters
    ...mapGetters('my_module', ['property']),
    // Accessing non-root properties
    ...mapState('my_module', {
      property: state => state.object.nested.property,
    }),
  },

  methods: {
    // Accessing actions
    ...mapActions('my_module', ['myAction']),
    // Accessing mutations
    ...mapMutations('my_module', ['myMutation']),
  },
};

It doesn't matter how small or how big is your project, it will be ready to scale, you can read here a bit more about Vuex and Namespaces.

Frontend

I learned that Vue has a smaller learning curve than Angular, and it is very similar to React(Note: assuming you have a strong base of Javascript, otherwise the curve is high on either of them).

As a dev who was mostly involved in Angular projects, understanding the core concepts and starting to be productive was easier than expected; I really think that the other way around must be harder, cause Angular has its own world.

Also learned about some core concepts that made my development faster and easier:

  • Atomic Design Pattern: structure your folders as =>
    • Atoms: these are basic components, dummy ones; could be buttons, inputs, dropdowns, any imagiable component small enough to be functional and testable
    • Molecules: a group of Atoms, at this level just a little logic included, it should not include communication with you state(if possible)
    • Organisms: mixture!, can have Atoms and Molecules, at this tier communication with you State can be allowed; Mappers, Getters, here are accepted
    • Templates: here you add together the aforementioned structures
    • Pages: every page you add is an instance that can be accessed from your routing strategy
  • Vue Lazy Routing: it is trivially easy to lazy load the route components; after defining your routerOptions in 5 lines of code it is set and done.
import Vue from 'vue';
import Router from 'vue-router';

const routerOptions = [
  { path: '/', component: 'Home' },
  { path: '/home', component: 'Home' },
  { path: '/auth', component: 'Auth' },
  { path: '*', component: 'Auth' },
];

const routes = routerOptions.map(route => {
  return {
    ...route,
    component: () => import(/* webpackChunkName: "{{route.component}}" */ `../views/${route.component}.vue`),
  };
});

Vue.use(Router);
  • Vue Test Utils: Vue has its own utils for testing purposes, and it is quite easy to understand and use, let me show the most simple sample I found:
<template>
  <div class="modal" data-test="modal" aria-modal="true">
    <div class="modal-content">
      <slot></slot>
    </div>
  </div>
</template>
import { expect } from 'chai';
import { shallowMount } from '@vue/test-utils';
import BaseModal from '@/components/atoms/BaseModal.vue';

describe('BaseModal', () => {
  context('Template', () => {
    context('existence of the element', () => {
      it("should exist 'modal' element", () => {
        const wrapper = shallowMount(BaseModal);
        expect(wrapper.find("[data-test='modal']").exists()).to.equal(true);
      });
    });
  });
});
  • Global Registration of Components: There are components widely used, these are candidates to be registered globally so they can be referenced without importing them. An easy way to accomplished this is creating a _globals.js file and fill it in with:
// Globally register all base components for convenience, because they
// will be used very frequently. Components are registered using the
// PascalCased version of their file name.

import Vue from 'vue';

// https://webpack.js.org/guides/dependency-management/#require-context
const requireComponent = require.context(
  // Look for files in the current directory
  './atoms',
  // Do not look in subdirectories
  false,
  // Only include .vue files
  /[\w-]+\.vue$/,
);

// For each matching file name...
requireComponent.keys().forEach(fileName => {
  // Get the component config
  const componentConfig = requireComponent(fileName);
  // Get the PascalCase version of the component name
  const componentName = fileName
    // Remove the "./" from the beginning
    .replace(/^\.\//, '')
    // Remove the file extension from the end
    .replace(/\.\w+$/, '');
  Vue.component(componentName, componentConfig.default || componentConfig);
});

After that, just import that file in main.js file:

import '@/components/_globals';

Some other good practices can be found:

Conclusion

As shown above, I had a long way during the last 18 months, I'm giving my two cents in here in the way I understood the concepts, and what I think were the best practices applied; maybe you could have a better way to do it, let's discuss in a thread below!

Thanks for reading!

43