You might have heard the term “service” in relation to a Vue application. But looking through the Vue documentation, you might find that there isn’t any mention of what a service is at all.

So when someone says “Just put that in a service”, what is that supposed to mean and what are you supposed to do about it?

What is a service?

When someone mentions adding a service to an application, that just means that you are going to create a JavaScript file that will export something for you to use in your application. This could be something that calls an API or formats dates or does some other focused piece of functionality for your application. And that’s all it does, focus is the key here.

Where to put services

Where do we put our services? I like to put them in a directory right next to the component directory and call it services.

📂 src/
 ⤷ components/
 ⤷ services/

Service examples

What goes into a service is usually based on what you need that service to do. If it’s a simple function, you can create a file that exports the function:

export function formatErrors(errors) {
  const formattedErrors = {};

  errors.forEach(error => {
    if(! formattedErrors[error.field.name]) {
      formattedErrors[error.field.name] = [];
    }

    formattedErrors[error.field.name].push({
      message: error.message,
      link: error.moreInfoUrl
    });
  });

  return formattedErrors;
}

Then import it into your component or other Vue script, with this:

<script>
  import { formatErrors } from '../services/formatErrors.js';

  export default {
    ...
    computed: {
      formattedErrors() {
        return formatErrors(this.errors);
      }
    }
    ...
  }

Now you can write unit tests for that method easily and use it in all the components that might need it.

What about an API? Many APIs have multiple ways of interacting with it, so one function won’t be enough. But you can group your API calls into an object that you can use for all of the functions:

import axios from 'axios';

axios.defaults.withCredentials = true;

export default {
  getCluster(id) {
    return axios.get('/api/cluster/' + id).then((response) => {
      return response.data;
    });
  },
  addCluster(name) {
    return axios.put('/api/cluster', { name: name }).then((response) => {
      return response.data;
    });
  }
};

Now you can use this export in your code:

import ClusterApi from '../services/ClusterApi.js';

export default {
  ...
  mounted() {  ClusterApi.getCluster(window.location.href.split('/').pop()).then(
      (cluster) => {
        this.points = cluster.places.map((place) => {
          return {
            lng: place.location.coordinates[0],
            lat: place.location.coordinates[1],
          };
        });
      }
    );
  },
  ...
};

So that’s what services are, focused pieces of reusable and testable code that you can use across your application. There’s nothing above that’s specifically a Vue concept, but thinking of any logic in your application as a collection of services can help you structure everything in a more maintainable way.