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.
Top comments (7)
Generally speaking the idea of services is universal across languages and architectures. This unit of work should handle most of the logic, leaving controllers to do as little heavy lifting as possible( In Vue scenario: Let Vue handle synchronization between DOM and javascript, rest can be done in service). It's much easier to reuse. Testing plain old javascript is much easier to test than Vue component, thus: If you don't need Vue magic, let's create a service - that is my approach.
I even suggest to use factory pattern to create new data from old data. I've been playing with repository pattern too, but it seemed like kinda of overkill.
Cool post! I’ve never seen services used to export functions other than for API calls. Is there a best practice for exporting function through services or should they be refactored as filters/mixins?
Good question! I think this is a hard one to answer though. I always have to think "What am I using this service for?" and "How applicable will this service be outside of Vue?"
If the service is really only for my Vue application or even for a couple of components, I'll make it a Vue mixin or filter. (I'm starting to get away from filters because they aren't supported in Vue 3.)
If they can be used outside of Vue or maybe by other classes in a Vue-based application, I'll export functions or an object instead. Regular JavaScript and TypeScript code doesn't really understand the Vue mixin, so making them regular functions or objects make them more universally usable by other parts of my system or other applications I may build and want to use them in.
Thank you for the question!
Thank you for the answer! Hmm it definitely makes sense to create the services around its usage in a Vue app. I agree, filters aren’t the best and are deprecated in v3 and mixins... well have their own downfalls, but this explains the usage of services well. Going to learn more about this and thank you! 😄🙌🏼
Great article!
Services also can be used in Nuxt as plugins
custom react hooks are awesome for this.
When you said service i was starting to wonder, Nice post tho.