DEV Community

Cover image for Architecting HTTP clients in Vue.js applications for efficient network communication

Architecting HTTP clients in Vue.js applications for efficient network communication

Musthaq Ahamad on October 20, 2019

Modern web apps highly rely on network communication with API servers and external services. From real-time data to static assets, everything is do...
Collapse
 
itshivat profile image
Albert Hidalgo 🐘

in the axios intance is baseURL not baseUrl


const httpClient = axios.create({
    baseURL: process.env.VUE_APP_BASE_URL,
    headers: {
        "Content-Type": "application/json",
        // anything you want to add to the headers
    }
});

Thanks!

Collapse
 
haxzie profile image
Musthaq Ahamad

Thanks for letting me know 😉✨

Collapse
 
nop33 profile image
nop33.eth

If you could update the post, that'd be great! I was banging my head for a bit until I figured out the typo :)

Collapse
 
sonicoder profile image
Gábor Soós

Hi,

Can you explain to me this mapping? My first thought was the getUsers is the function, but it is an array instead?

    computed: {
        ...mapGetters('Users', ['getUsers'])
    },
    methods: {
        ...mapActions('Users', ['fetchUsers'])
    },
    mounted: {
        // Make network request if the data is empty
        if ( this.getUsers.length === 0 ) {
            // set loading screen
            this.isLoading = true;

            this.fetchUsers().then(() => {
                this.isLoading = false;
            }).catch(err => {
                // show error screeen
            });
        }
    }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
haxzie profile image
Musthaq Ahamad

It's the getter defined in the store. Getters acts as computed properties so they're not called like a function.

Collapse
 
sonicoder profile image
Gábor Soós

I know how a simple getter works, you pass in an array and it maps the getters. In your example, there is also the 'Users' before the array element.

Thread Thread
 
haxzie profile image
Musthaq Ahamad • Edited

When we create modules in a Vuex store, that is; you split your store into smaller stores. It's a good idea to namespace them. Eg, if you have an application that has a store, you can create modules inside it for User data, Post data and so on. When you have modules, you need to pass the module name (or the namespace) to get the getter/action from that module to mapping functions. You can read more about this from my previous Article "Architecting Vuex store for large scale Vue.js application".

In simple words, if you want to access the methods in a store module namespaced as Users, you would use Users/getUsers to access the getter. Instead of that, you can simply pass the module name as the first argument for mapGetters/mapActions to access methods from that module as I have used in the example :)

mapGetters(['Users/getUsers'])

is same as

mapGetters('Users', ['getUsers'])
Thread Thread
 
sonicoder profile image
Gábor Soós

Now it's clear, I used the mapGetters(['Users/getUsers']) notation for modules, not the other one

Thread Thread
 
haxzie profile image
Musthaq Ahamad

Awesome! Hope this helped you and hope you learned something handy :)

Collapse
 
haxzie profile image
Musthaq Ahamad

Hey, thanks for letting me know :)
This is a fairly simple fix to just check if error.response is present before switch-casing the error.response.status.

Will update the post with these changes.
Thank you.

Collapse
 
israeldiassoares profile image
Israel Soares

Thank you for share it with us !
Great approach/practices about Vue component, making more clear code and scalable.

Vue and Nuxt are great frameworks I like a lot.

I hope that you continues to sharing more content like this. I'm excited to see your next post.

Collapse
 
darthvitalus profile image
DarthVitalus

Hi, fellow! Thanks for such a valuable post! Saved it for future ;)

I've some questions though)

  1. Making network requests inside Vuex actions

Isn't it better to use async/await for clearer and more declarative code?
Some code above could be written like this:

const actions = {
    fetchUsers: async function ({ commit }) {
        const response = await getAllUsers();
        commit('SET_USERS', response.data);
    }
}

sure it needs try/catch around ;)

  1. Managing Auth Credentials using interceptors

Saving tokens or some other credentials/auth data to LS is bad, as spoken clearly here:
https://dev.to/rdegges/please-stop-using-local-storage-1i04
Do you still use this LS approach? Or you just used it as an easy example?

  1. Caching and Throttling

About this lines and idea:
"All the subsequent calls after the first call will be responded from the cache.

getUsers(); // actual network request and response gets cached
getUsers(); // from cache
getUsers(); // from cache...

"

What if in between these requests server's data has actually changed? Thus client will get wrong (cached) data. I believe caching is more server stuff to do, via response headers, telling browser what caching strategy to use, because server does better knowledge about information it stores, and about ways and frequency of data changes. So why not do caching on server-browser?

Thanks in advance!)

Collapse
 
haxzie profile image
Musthaq Ahamad

Great Observation! Thanks for the suggestions, I have updated the article with your feedback. And for the part where I used Local Storage, it's just for an easy example, adding to that using cookies instead of localStorage doesn't make much difference since both use the same security policy. Totally agree with implementing robust security in place without using localStorage but If your website is vulnerable to XSS, both the cases should be deemed to be flawed. Storing JWT in localStorage can be made more secure by issuing short term tokens. But yeah, choosing security and ease of implementation is always a matter of trade-offs between both. Thanks for your suggestions, hope it will help the readers alot! :)

Collapse
 
georgeben profile image
George Kurobara Benjamin

I signed up to DEV.to just to thank you for this article. Thank you.

Collapse
 
rizvanadnan profile image
Adnan Rizvan

same lol, @author - you a beast

Collapse
 
haxzie profile image
Musthaq Ahamad

Thanks George ✨

Collapse
 
sergx profile image
Sergey Khiluta

Thanks, but i did not get how to use vue-notifications.. it is very interesting for me, but i don't understend how use it here..

Collapse
 
sergx profile image
Sergey Khiluta

May be i figured it out.. I changed notify.warn('Nothing to display','Data Not Found'); to code below. Nice, that it works in Vuex actions the same, as in Vue components

Vue.notify({
  group: "default-top-center",
  type: "warn",
  title: "Nothing to display",
  text: "Data Not Found",
  //duration: 3000,
  speed: 500
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
haxzie profile image
Musthaq Ahamad

Haha, glad you were able to figue that out :)

Collapse
 
devhammed profile image
Hammed Oyedele

Nice article!
Actually, this applies also to React.

Collapse
 
cesarau0619 profile image
Cesar Augusto

Nice post.

Collapse
 
thisisthien profile image
Thien Nguyen

Nice write up.

Collapse
 
vsymonenko profile image
VSymonenko

Hi! What about HTTP2?

Collapse
 
achilleas01 profile image
achilleas01

great article!!! thank you

Collapse
 
willwinberg_64 profile image
William winberg

Dug

Collapse
 
mandeepm91 profile image
Mandeep Singh Gulati

Thanks a lot for taking the time to write such a thorough post! This was very helpful :-)

Collapse
 
abuoop profile image
Emad Al-Deen Mukhtar

Great article,
Keep going..