Intro
We all know that NuxtJS is an awesome framework. Unlike Angular which has a well structured folder for services, nuxt doesn't. But like every good nuxt developer, using services are essential, especially when you use VueX with NuxtJS.
Implementation of services in Nuxt
Before we implement services, make sure you have vuex, nuxtjs/axios installed in your project.
Into the plugins
directories, create a new file (e.g: service.js)
export default ({$axios}, inject) => {
inject('getProductList', async (params) => await $axios.get('cool_get_url', {
params
}))
inject('createProduct', async (data) => await $axios.post('cool_post_url', data))
// ... and so on
}
So, in our Nuxt Component, we can access those service within the context this
.
<template>
<div><!-- Make a liste of product--></div>
</template>
<script>
export default {
name: 'MyAwesomeProduct',
async mounted() {
// accessing $getProductList service using this
const { data } = this.$getProductList({type: 'awesome type'})
// accessing $createProduct service
const { data } = this.$createProduct({
name: 'awesome product'
})
}
}
</script>
Or if your system is more complicated, and you use vuex
, you can access those service within vuex store as well.
export default {
// some basic store configuration
actions: {
async getProductList({ commit }) {
const { data } = this.$getProductList({type: 'awesome type'})
// data manipulation before commit ...
commit('MY_AWESOME_MUTATION', data)
},
async createProduct({ commit }) {
const { data } = this.$createProduct({type: 'awesome type'})
// data manipulation before commit ...
commit('MY_AWESOME_MUTATION', data)
},
}
}
And within your component, you can use MapGetters
to retrieve data after calling the action using MapActions
Let refactor the code, My Best Practice
Now, time is coming, so let rewrite those services.
In the root of your project, you can create a folder called services, and within that folder, create a new file named product.js
(If you like, you can prefix it with service ๐ ). Here the content of that file:
export default ($axios) => {
return {
getProductList: async (params) => {
return await $axios.get('cool_get_url', {
params
})
},
createProduct: async (data) => {
return await $axios.post('cool_post_url', data)
}
// more verbs and more actions
}
}
Now, the file [service.js] within the plugins will look like this:
import productService from '~/services/product'
export default ({ $axios }, inject) => {
const allMethods = {
...productService($axios),
// import another service here
}
const methods = Object.keys(allMethods)
methods.forEach((method) => {
inject(method, allMethods[method])
})
}
We know that Object.keys(allMethods)
will return the keys of allMethods
, and then, we use those key, as the name of our services, and allMethods[method]
will return the methods within the services.
Now inject will contains small code, and it's more clear.
Our services are separated in new file.
Pros
- Separation of concern
- Clean code
- Easy for e2e testing
- Easy for unit testing
Cons
- More files to handle
- (Put in comments if you find another cons with this approach)
Now for deployment you can read this article which is about optimisation.
Note: I repeat it again, it's my own best practice that I use for any of our projects. If you find it usefull, feel free to use it. ๐
Top comments (18)
how to use it with Interceptors axios for refresh token when "token is invalid"? And save token, refresh token to cookies?
You can use interceptor and in onResponse you can check if your token is valid or not.
yes. when refresh token success but should I save token to vuex or cookies? thanks.
The simplest way is using localstorage to save your token.
But localStorage is client-side. How can i save it from server nuxtjs?
You can use this lib and use cookie for saving the info within nuxt server
can you give an example using lib or project using lib? tks you
You can see this doc
Hello guys, I have a question. This structure works also with typescript? Or it is necessary to do some modification?
Yes, this works with typescript
I use openapi-client-axios +
openapi.json
(i.e. Swagger) + TypeScript (optional).But I don't know how to inject to
$axios
.You can use nuxtjs/axios module and follow the installation intruction
Itโs a great best practices that i apply on my project but i precise a prefix due to multiple services. Nice sharing ๐
Thank you
Another negative is that this gets pretty overcrowded
It'd be better if you could do this.$services.user.getUsers()
nice post! can you add an example of how you ll test this service using vue-test-utils?
I like the pattern. What is your approach when runtimeconfig/environment variables is needed? I'm having a problem how composables are not available outside script setup. My bad it's for nuxt 3