TL; DR: заморозить материал в магазине Vue для повышения производительности

Я начал работать со своим первым приложением Vue пару месяцев назад. Кодовая база была довольно устоявшейся, и до этого у меня не было опыта работы с Vue или vuex. У меня был опыт работы с React и redux, поэтому мир Vue был для меня новым. Приложение, с которым я работал, представляет собой онлайн-платформу, которая имеет функции, подобные электронной коммерции, и чат, который использует соединение Socket через библиотеку vue-socket.io.

Поработав какое-то время над проектом, я заметил, что если сайт открыт 10–15 минут, он начинает жрать CPU. Как много. После обновления страницы еще 15 минут все нормально. Затем вентилятор моего Macbook снова выходит из строя.

Что здесь происходит? 🤔

Чтобы выяснить, в чем проблема, я позволил сайту бездействовать в течение 15 минут и открыл инструменты Производительность Chrome, чтобы записать некоторые кадры. Причина медлительности была довольно ясна: добавление новых сообщений чата в магазин могло длиться бесконечно.

Были вызовы какой-то таинственной _traverse функции, которая была рекурсивной. Причина этого была найдена в исходном коде Vue. Этот _traverse собирает все объекты как глубокую зависимость, так что, если какой-либо объект изменяется, он может уведомить правильные геттеры.

Решение 🙏

Как избежать медленного рекурсивного сбора, было довольно просто: просто заморозить все. Поскольку наши сообщения никогда не редактируются, замораживание файлов быстро исправляется и не вызывает никаких побочных эффектов.

До исправления добавление новых сообщений выглядело так:

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

Чтобы решить эту проблему, я просто заморозил все сохраненные сообщения. Таким образом, vuex не будет собирать их как глубокую зависимость.

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);
  }
},

Если бы пользователь мог редактировать свои сообщения после отправки, нам пришлось бы скопировать исходное сообщение в новый объект, применить там обновления и сохранить его в хранилище с помощью Vue.set. В противном случае он не будет правильно обновляться в пользовательском интерфейсе.

Теперь сайт может простаивать целую вечность, не съедая весь процессор. Ура! 🤗

Следующий? 🤓

Если у вас есть другие советы по повышению производительности Vue, оставьте комментарий! 📩

Я энтузиаст технологий и разработчик программного обеспечения, страстно увлеченный идеальным дизайном. Мне очень нравится создавать новые вещи, особенно когда это связано с технологиями.

Если вам понравился этот пост, подпишитесь на нас, чтобы быть в курсе последних тенденций в области технологий и дизайна 🤓

Следите за Perfektio в Facebook / Twitter / Instagram 😍