Страдания по VueUse

VueUse - популярная библиотека, состоящая из небольших утилит и в среде Vue разработчиков, идущая как "must have" наряду с Pinia. Нисколько не умаляя вклад Anthony Fu в экосистему Vue, опишу, почему я не использую её и не рекомендую для серьезных проектов и опытных разработчиков.

  1. Все утилиты в ней - небольшие. Под "небольшие" я подразумеваю, что аналогичный свой код будет в 10-50 строк. В зависимости от обстоятельств и требований, свой код может быть и в пять строк (аналог onClickOutside), и в две (использование LocalStorage). Кроме того, на проект нужно обычно всего 2-3 подобных утилит оттуда. Подключать из-за этого всю библиотеку нецелесообразно, несмотря на tree-shaking.

  2. Это зависимость, и как все зависимости может измениться, устареть, получить уязвимость, тормозить развитие проекта и прочее, прочее. С большинством активно развивавшихся библиотек такое случалось.

  3. Утилиты в ней не делают то, что надо именно тебе. Например, мне для адаптивности нужно ставить соответствующий динамичный CSS класс на <body> при изменении ширины экрана. В библиотеке есть две утилиты, работающие с шириной экрана, но ни одна не дает именно то, что надо. Приходится преобразовывать данные от useBreakpoints в свои, и весь код занимает половину кода своей реализации, которая достаточно проста и прямолинейна, и вполне может быть даже сгенерирована AI ботом.

  4. В утилитах VueUse содержится избыточная и чрезмерная логика и код (с точки зрения вашего конкретного проекта). Если бы это был простой js код, было бы еще ничего, но это реактивный код. Если открыть исходники useBreakpoints, то можно увидеть с десяток computed переменных, которые ты не используешь.
    Но учитывая, что только в версии 3.4 Vue пофиксила баг, при котором компьютеды пересчитывались, хотя ни одна из входящих в них переменная не менялась, нет никаких гарантий, что при изменении экрана или сдвиге мышки не будет производиться множество не нужных тебе пересчетов. Это влияет на производительность.

  5. Указанная выше проблема, это не недостаток именно VueUse. Попробуйте написать универсальный компонент, который любой разработчик мог бы использовать. Примерно за 20% времени вы напишите вполне рабочий, подходящий вашему проекту компонент, и оставшиеся 80% будете лепить на него обвесы, чтобы он был универсальный и опциональный, учитывал Vue 2 и Vue 3, был SSR-safe и еще много чего, что конкретно вам не нужно.
    В итоге лаконичный красивый эффективный код после универсализации превратится во множество проверок, адаптеров и прочей не функциональной логики. Поэтому написать свой код всегда намного эффективней использования чужого универсального. Речь сейчас идет конкретно про подобные утилитарные библиотеки, а не, к примеру, UI пакеты.

  6. useLocalStorage от VueUse возвращает реактивную переменную, которую, по идее, нужно напрямую использовать в проекте. Другими словами, если мне надо сохранять в LocalStorage shoppingCart, то ее нужно создать через вызов useLocalStorage(). То есть, одна из основных бизнес-сущностей моего проекта должна создаваться какой-то сторонней библиотекой. Чужой код простой утилиты диктует реализацию элементов архитектуры всего проекта. Мне такое кажется абсолютно неприемлемым.

  7. Можно создать отдельно shoppingCart и отдельно переменную через useLocalStorage() и затем заморочится с их синхронизацией через watch и предотвращением бесконечных циклов. И это для каждой такой переменной. Можно совсем довериться VueUse и использовать их syncRef. Но это уже даже не неприемлемо, а смешно, не говоря о том, что код в итоге получится больше, чем своё решение.
    Таким образом, утилиты VueUse бывают просто неудобными в примененииLodash при использовании был очень удобным - берешь её функцию, и она максимально эффективно делает то, что надо. Из того, что я пытался применить в свои проекты, VueUse неудобен.

    Для примера, кастомная версия useLocalStorageзанимает 35 строк и позволяет реактивно отобразить в LocalStorage любую реактивную переменную проекта просто зарегистрировав её.

  8. VueUse делается человеком, у которого свой взгляд на разработку. Иногда у него получаются вещи, которые я активно использую (eslint-config), а иногда он, с моей точки зрения, пытается из Vue сделать конструктор типа Тильды для привлечения программеров невысокого уровня.
    Есть большая разница между популяризацией (хорошо) и популизмом (плохо). Советы по использованию и даже навязывание VueUse разработчикам, без понимания ими того, что именно они получают и за какую цену, смахивает на второе..

Wikipedia

Попули́зм (от лат. populus — народ) — политика, апеллирующая к широким массам и обещающая им скорое и лёгкое решение острых социальных проблем. В основе популизма лежит стремление той или иной политической силы завоевать доверие и поддержку масс, понравиться народу. При этом реальные цели политиков-популистов (борьба за власть, обогащение и тому подобное), как правило, прикрываются социально-привлекательными идеями.


Интересная и полезная информация о Vue.js и фронтенде в целом на нашем сайте: Vue‑FAQ.org и Телеграм‑канале: @vuefaq

@gmtd
08.02.2024 21:49 UTC
Первоисточник

Комментарии

@Ilusha
09.02.2024 00:50 UTC
+9

VueUse - это прекрасное место, чтобы посмотреть «а что, так можно было». Библиотека примеров.

Многие перечисленные минусы для одного проекта - это плюсы для другого.

Зависимость? Да. Документированная, с тестами, написанная крутым разработчиком, бесплатная для тебя. Tree-shaking лишнее отрежет, не понял вообще посыла выбросить его из уравнения.

На эту зависимость завязана бизнес-логика? Открой код, посмотри - подходит ли тебе это. Или здесь только «фатальный недостаток»?

Библиотека будет развиваться и перестанет тебе подходить? Форкай, выкидывай лишнее, модернизируй.

Универсальная? Да. Дофига проектов, которые будут еще годы переезжать с Naruto на vue3.

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

Доступность разработкам не высокого уровня? Гугл целый язык создал - go lang, чтобы было проще.
Но, я с этим тезисом не согласен относительно vueuse. Утилиты часто довольно сложные для понимания: нужно залезть в код, чтобы «дошло».

Диктует архитектуру? Что ж за архитектур такой, что набор мелких утилиток без какой-либо философии диктует что-то? Может просто архитектурной концепции не было? Делает как где-то видел и плывет по течению?

В общем, как всегда, люди ругают молоток, а не плотника.
Я помню время, когда люди также ругали за использование underscore/lodash - лучше ведь писать свое. Как писали свой jQuery. У которого, кстати, 3 дня назад вышла 4 версия в бету.

@sfirestar
09.02.2024 11:35 UTC
+2

Про популизм в конце улыбнуло.

Ну не подходит - не используйте. Лично я считаю VueUse отличным сборником иногда по-настоящему целебных макросов. Отлично подходит, чтобы не писать лишний раз boilerplate код, особенно когда у браузеров отличаются реализации (привет, useClipboard).

Да, это подходит в основном для типичных use-case-ов, но в этом и суть инструмента. Если нужно что-то кастомное - пилите сами. Но зачем из-за этого хаять отличную библиотеку - не очень понятно.

@Solant
09.02.2024 21:56 UTC
+2

Все утилиты в ней - небольшие

И это прекрасно: одна общая библиотека реактивных примитивов и адаптированных под реактивность браузерных функций. Эдакая std для vue которой нет в самом vue

Это зависимость

Как и сам vue, но она очень сильно облегчает работу, поэтому это просто trade-off

Утилиты в ней не делают то, что надо именно тебе

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

избыточная и чрезмерная логика и код

Composabl'ы из библиотеки поддерживают 2 и 3 версии vue, по возможности дружат с Nuxt'ом и vue-router'ом, а также поддерживают SSR и уже пофиксили баги о которых невозможно знать заранее при разработке "в лоб"

диктует реализацию элементов архитектуры всего проекта

Вы привели пример исходного кода своего проекта интернет магазина которому мешает архитектура vueuse, но я вижу проблемы с архитектурой:

  1. Отсутствует поддержка SSR, и ее нельзя будет подключить без переписывания части утилит (довольно серьезная проблема для интернет магазина, где важна отдача данных внутри html для поисковых ботов)

  2. Отсутствует code splitting по роутам, из-за чего у приложения один большой бандл

  3. Не вижу в проекте каких-то требований к супер сложным вычислениям, где считался бы каждый computed (это не повод плодить лишние, я согласен, но это также не повод делать велосипеды с возможными багами)

Из беглого осмотра проекта, как минимум две вышеперечисленные проблемы можно решить, либо минимизаровать, с помощью vueuse. Поэтому считаю совет "не берите vueuse, пишите сами" как минимум вредным

@zede
10.02.2024 08:30 UTC
+2

И действительно важной ни одной причины.

  1. Да они небольшие. Но вот эту пачку утилит которую все пишут как попало. Таскают из проекта в проект накапливая устаревания, бед-практисы и тд. Часто на вопрос: а на кой эта утилита? Ответ: ну вот из проекта в проект таскаю привык уже. Так что единая точка для утилит: замечательный выбор. Они всегда протестированы, задокументированы и поддерживаются силами всего сообщества

  2. Зависимость и зависимость. Проблем от создания велосипедов гораздо больше: неожиданные корнер-кейсы. Дополнительная точка для тестирования и потенциальная проблема (Ваш пример с useLocalStorage тоже не с первого коммита заработал корректно. Мне бы хватило взять функцию и не переживать о остальном)

  3. Да они могут делать что-то другое что в 90%+ случаев будет более подходящим. Пример опять вышел мимо:

const breakpoints = useBreakpoints({
  desktop: 1800,
  notebook: 1200,
  tablet: 480,
  mobile: 0,
}).current()

// Так как vueuse возвращает нам все подходящие брикпоинты, то берем самый большой
const currentBreakpoint = computed(() => breakpoints.value[0])

// Тут и комментировать нечего, код нагляднее некуда
watch(currentBreakpoint, (newBreakpoint, oldBreakpoint) => {
  document.body.classList.remove(oldBreakpoint)
  document.body.classList.add(newBreakpoint)
}, { immediate: true })

О какой половине шла речь? Специально сравнил с предоставленными исходниками. Я предпочту поддерживать вариант с vueuse. Тут ровно 5 строк предельно понятной логики. Те разница почти в 8 раз и не надо думать что там идет не так.

  1. Как вы и сказали это реактивный код. И дополнили "которые ты не используешь". Да, вью реактивный и это почти полностью компенсирует сказанное в статье. Неиспользуемые вычисляемые свойства на которые нет подписчиков... не обновляются. Во Vue pull модель реактивности. Нет подписки - нет обновления. И комментарий о Vue 3.4 тут не причем, он влияет лишь на вычислимые свойства с подписками. Поэтому аргументация тоже вышла мимо. Хотя да, часто избыточная логика может присутствовать чтобы покрыть различные кейсы или закрыть граничные случаи, но которые для большинства не критичны, что в теории в какой-то момент может спасти от выстрела в ногу.

  2. "написать свой код всегда намного эффективней". Это если хватает компетенции. Если не хватает, то можно получить монстров гораздо страшнее чем универсальное решение от опытного разработчика. (тут оставлю ремарку, что читать исходный код таких библиотек очень полезно, даже если решил реализовать по-своему, то проще взять универсальное и отрубить ненужное, опять же экономит время и силы)

  3. А еще ваше приложение работает на Vue. Ну какой-то совсем притянутый за уши аргумент. В чем же критичность того что создается не ref / reactive а уже готовый ref и watch к нему? Да и какая диктатура архитектуры. Это утилиты, пользуйся в той мере насколько и как надо.

  4. Удобно, не удобно. Слишком субъективно. Мне вот удобно, вам нет. На чем сойдемся? Для чего делать отдельную переменную и синхронизировать ее тем более непонятно. Исключение: вы хотите работать с LS только по какому-то событию, но это уже совсем другая логика.

  5. Как выше заметили. "Пишите все сами", если это не джун который разбирается в азах - такой же популизм.

Добавлю от себя:

  1. Выбор что использовать, а что нет - за вами

  2. Если вы берете SPA, то не факт что вам не понадобится SSR в будущем. Тут же поддержка из коробки

  3. Как хорошо выше заметили: чем больше людей используют vueuse тем проще людям вкатываться в проект

@doomguy49
12.02.2024 11:15 UTC
0

Подключать из-за этого всю библиотеку нецелесообразно, несмотря на tree-shaking

И почему же? Это совершенно не так

Это зависимость, и как все зависимости может измениться, устареть, получить уязвимость, тормозить развитие проекта и прочее, прочее

Любой код может измениться, устареть, получить уязвимость, тормозить развитие проекта, в том числе написанный собственноручно, и что дальше? Это не проблема библиотеки, а реалии программирования

Утилиты в ней не делают то, что надо именно тебе.

Опять же - очень субъективно. Утилиты, которые мы используем, делают именно то что нам нужно, и часто лучшим способом

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

Как так-то? В документации есть линки на исходный код, есть DevTools, позволяющие проанализировать потребление памяти, обработчики и фпс, просто надо смотреть внимательно что происходит, что необходимо и что навешивается

Я не увидел здесь аргументов, которые относились бы конкретно к VueUse, а не программированию в целом или программисту. Нельзя сделать библиотеку, которая бы использовалась на 100%, не устаревала со временем и была лишена всех перечисленных недостатков. VueUse - это отличная, тришейкающаяся либа, которая покрывает приличное количество рутинных задач и поддерживается другими людьми, дающая возможность сконцентрироваться на бизнес-логике приложения

@gmtd
12.02.2024 11:51 UTC
0

А Tanstack не используете?