Какие альтернативы Vuex вы использовали и почему?

С момента выхода Vue 3 и появления Composition API, сообщество начало активно искать альтернативы Vuex, ориентированные на модульность, простоту и тесную интеграцию с реактивностью ref и reactive. Vuex, особенно в версиях 3 и 4, имел устаревший синтаксис с обязательными mutations, actions, громоздкой структурой и отсутствием type-safety по умолчанию. В больших и современных проектах начали использоваться более легковесные и декларативные подходы. Ниже представлены ключевые альтернативы Vuex, которые я использовал, с техническим обоснованием и реализационными примерами.

1. Pinia

Почему выбрана:

Pinia — официально рекомендуемая альтернатива Vuex от команды Vue. Полностью совместима с Vue 3, поддерживает Composition API, TypeScript из коробки, SSR и Devtools. Простая, модульная, без разделения на mutations, actions и getters.

Пример:

// stores/useUserStore.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
name: '',
isAdmin: false
}),
actions: {
login(name: string) {
this.name = name
}
},
getters: {
isLoggedIn: (state) => !!state.name
}
})
// в компоненте
const user = useUserStore()
user.login('admin')

Преимущества:

  • Простота (никаких mutations)

  • Поддержка devtools, SSR

  • storeToRefs() для реактивных ссылок

  • Расширения (pinia-plugin-persistedstate, pinia-orm)

2. Composition API + Composables (без Pinia)

Почему выбрана:

При простом или среднесложном состоянии можно обойтись без полноценного стор-решения. Используется подход composable-функций с использованием ref, reactive и обычных функций.

Пример:

// useCart.ts
import { ref } from 'vue'
const items = ref(\[\])
export function useCart() {
const addItem = (item) => items.value.push(item)
const totalItems = computed(() => items.value.length)
return { items, addItem, totalItems }
}
// в компоненте
const { items, addItem } = useCart()

Преимущества:

  • Не требует сторонних библиотек

  • Идеально для локального или модульного состояния

  • Отлично работает с TypeScript

Минусы:

  • Нет devtools

  • Сложно масштабировать глобальное состояние без соглашений

3. Vue Observable (Vue 2, до Composition API)

Почему использовалась:

До появления Composition API и до Vuex 4 некоторые проекты использовали Vue.observable() для создания реактивного состояния вручную.

// store.js
import Vue from 'vue'
export const store = Vue.observable({ count: 0 })
export const mutations = {
increment() {
store.count++
}
}

Минусы:

  • Нет модульности

  • Не поддерживается во Vue 3

4. Redux Toolkit (в гибридных проектах с Vue и React)

Почему использовалась:

В проекте с общей бизнес-логикой между React и Vue использовался Redux Toolkit с экспортируемыми стор-конфигурациями.

// slice.ts
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => {
state.value++
}
}
})

Интеграция с Vue:

Использование @reduxjs/toolkit через store.subscribe() + computed для реактивности. Такой подход оправдан при необходимости использования единого хранилища между фреймворками.

5. Zustand (в микрофронтах или Web Components)

Почему использовалась:

Zustand — минималистичный, эффективный store от авторов Jotai/React Spring. Использовался в микрофронтах, взаимодействующих с Vue и React.

const useStore = create((set) => ({
count: 0,
inc: () => set((state) => ({ count: state.count + 1 }))
}))

Для Vue применялся reactive(useStore.getState()) и store.subscribe().

6. RxJS (реактивная модель)

Почему использовалась:

Для сложных асинхронных сценариев (формы, валидация, данные из WebSocket) использовались BehaviorSubject, Observable, интеграция с Vue через ref() и подписки.

const subject = new BehaviorSubject(0)
export function useRxCount() {
const count = ref(subject.value)
subject.subscribe((val) => {
count.value = val
})
const increment = () => subject.next(subject.value + 1)
return { count, increment }
}

Преимущества:

  • Явное управление потоками

  • Обработка множественных событий и состояний

  • Отлично сочетается с Vue's watchEffect и ref

Минусы:

  • Высокий порог входа

  • Избыточен для большинства CRUD-приложений

7. VueUse и useStorage, useSessionStorage

Почему использовалась:

В проектах, где состояние нужно синхронизировать с localStorage/sessionStorage, использовались готовые решения из VueUse.

import { useStorage } from '@vueuse/core'
const token = useStorage('auth_token', '')

Преимущества:

  • Реактивность + персистентность

  • Нет необходимости создавать отдельный store

  • Отлично подходит для settings/preferences

8. Apollo Client Cache (в GraphQL-проектах)

Почему использовалась:

В GraphQL-приложениях (например, при использовании Hasura) данные кэшировались через Apollo Client, который автоматически управлял состоянием.

import { useQuery } from '@vue/apollo-composable'
const { result } = useQuery(GET_USER)

Также возможна запись кэша вручную:

apolloClient.writeQuery({
query: GET_USER,
data: { user: { id: 1, name: 'Alex' } }
})

Преимущества:

  • Нет необходимости дублировать состояние между API и store

  • Автоматическая нормализация, рефетчи, обновление кэша

9. Effector (в проекте с высокими требованиями к предсказуемости)

Effector — декларативный и функциональный state manager с чёткой моделью и масштабируемостью. В Vue используется с обёртками (effector-vue).

import { createStore, createEvent } from 'effector'
const increment = createEvent()
const $count = createStore(0).on(increment, (state) => state + 1)

Для Vue:

import { useStore } from 'effector-vue/composition'
const count = useStore($count)

Преимущества:

  • Поддержка event-driven архитектуры

  • Хорошая масштабируемость

  • Идеален для систем с высокой сложностью состояний

10. Сравнительная таблица

Инструмент Vue 3 Support Devtools TypeScript SSR Подходит для
Pinia Любые Vue 3 приложения
--- --- --- --- --- ---
Composables (ref) Простые, модульные задачи
--- --- --- --- --- ---
Vue.observable ❌ (только Vue 2) Легаси-проекты
--- --- --- --- --- ---
Redux Toolkit ✅ (опционально) Кросс-фреймворк проекты
--- --- --- --- --- ---
Zustand ⚠️ через обёртку Микрофронты, shared stores
--- --- --- --- --- ---
RxJS Сложные async-сценарии
--- --- --- --- --- ---
VueUse Персистентные состояния
--- --- --- --- --- ---
Apollo Client GraphQL-клиенты
--- --- --- --- --- ---
Effector Высоконагруженные SPA
--- --- --- --- --- ---