Nuxt like a pro. Use service pattern (My Best practice)
Tags: nuxt, vue, javascript
Published: 2021-03-15 19:17:19

## 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](https://vuex.vuejs.org/), [nuxtjs/axios](https://axios.nuxtjs.org/) installed in your project.

Into the `plugins` directories, create a new file (e.g: service.js)

```javascript
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`.

```html
<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.
```javascript
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:

```javascript
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:
```javascript
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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/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](https://dev.to/radonirinamaminiaina/let-obfuscate-it-optmisation-technic-gd1) 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. 😇