How to improve performance of vuex store

TL;DR: Freeze stuff on Vue store for improved performance

I started working with my first Vue application couple of months ago. Codebase was pretty established and I had no prior experience of Vue or vuex before that. I had experience with React and redux so world of Vue was new to me. Application that I was working with is an online platform which has ecommerce-like features and a chat that uses Socket connection through vue-socket.io library.

After working on the project for a while, I noticed that if the site is open for 10–15 minutes, it starts to eat CPU. Like a lot. After refreshing page, everything is fine for another 15 minutes. Then my Macbook’s fan goes through the roof again.

😐

What is going on? 🤔

To find out what the problem was, I let the site idle for 15 minutes and opened Chrome’s Performance tools to record some footage. The reason for slowness was pretty clear: adding new chat messages to the store could take forever.

102ms for adding a new message is 100ms too much

There were calls to some mystery _traverse function that was recursive. Reason to this was found from Vue source code. That _traverse collects all objects as deep dependency, so that if some Object changes, it can notify the correct getters.

https://github.com/vuejs/vue/blob/e7b912a17bf3be6b1743307ce359a9c6816be0dd/dist/vue.js#L2126

Solution 🙏

It was pretty simple how to avoid the slow recursive collection: just freeze everything. Since our messages are never edited, freezing stuff is fast fix and won’t cause any side effects.

Before the fix, adding new messages looked like this:

SOCKET_msg(state, payload) {
state.messages.push(payload);

if (state.messages.length > 100) {
state.messages = state.messages.slice(-100);
}
},

To fix the the issue, I just froze all messages that were saved. That way vuex wont collect them as deep dependency.

SOCKET_msg(state, payload) {
const message = { ...payload };

// Freeze message to prevent slow '_traverse' calls made by Vue
Object.freeze(message);
state.messages.push(message); if (state.messages.length > 100) {
state.messages = state.messages.slice(-100);
}
},

If user could edit their messages after sending, we would have to copy the original message to new Object, apply updates there and save it to store with Vue.set. Otherwise it wouldn’t update correctly on the UI.

Now the site can idle open for ages without eating all the CPU. Yay! 🤗

Next? 🤓

If you have other tips to improve Vue performance, leave a comment! 📩


I’m a technology enthusiast and software developer with passion to pixel perfect design. I really love building new things, especially when it involves technology.

If you liked this post, follow us to receive the latest trends in tech & design 🤓


Follow Perfektio on Facebook / Twitter / Instagram 😍

Jonne Huotari

Written by

Developer, Designer & Co-founder at Perfektio 💎 Passionate about beautiful code and design 😍

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade