Pydantic v2: что нового, миграция с v1 и реальные бенчмарки
В 2026 году спор «Zustand или Redux Toolkit» — это уже не холивар фанатов, а практический выбор архитектуры. Оба инструмента зрелые, оба поддерживают TypeScript из коробки. Но подходят они для разных ситуаций. Разберём с кодом, цифрами и чеклистом в конце.
Архитектурные отличия: store, slices, middleware
Redux Toolkit (RTK) строится вокруг единого store с разделением на slices. Каждый slice — reducer + actions + начальное состояние:
import { configureStore, createSlice, PayloadAction } from '@reduxjs/toolkit';
interface CounterState { value: number }
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 } as CounterState,
reducers: {
increment(state) { state.value += 1 },
incrementBy(state, action: PayloadAction<number>) {
state.value += action.payload;
},
},
});
export const store = configureStore({
reducer: { counter: counterSlice.reducer },
});
Zustand — минималистичный store без boilerplate. Нет slices, нет dispatch, нет action creators:
import { create } from 'zustand';
interface CounterStore {
value: number;
increment: () => void;
incrementBy: (n: number) => void;
}
export const useCounterStore = create<CounterStore>((set) => ({
value: 0,
increment: () => set((s) => ({ value: s.value + 1 })),
incrementBy: (n) => set((s) => ({ value: s.value + n })),
}));
Ключевое отличие: в RTK логика обновления отделена от состояния (reducers), в Zustand — методы живут рядом с данными. RTK навязывает структуру, Zustand даёт свободу.
Размер бандла и tree-shaking
- Zustand — ~1.1 KB (minified + gzip). Без зависимостей. Полностью tree-shakeable.
- Redux Toolkit — ~12-14 KB (redux + immer + RTK). Immer один весит ~6 KB.
Для SPA разница некритична. Но для виджетов, Chrome-расширений или Astro islands с бюджетом 50 KB — Zustand выигрывает однозначно.
DevTools и отладка
Redux DevTools — золотой стандарт: time-travel, diff состояний, запись сессий. RTK подключает их автоматически.
Zustand тоже поддерживает Redux DevTools через middleware:
import { devtools } from 'zustand/middleware';
const useStore = create<MyState>()(
devtools(
(set) => ({
count: 0,
inc: () => set((s) => ({ count: s.count + 1 }), false, 'inc'),
}),
{ name: 'MyStore' }
)
);
Работает, но без автоматических имён экшенов — надо передавать третьим аргументом в set. Time-travel менее надёжен при сложных обновлениях. Для серьёзной отладки RTK удобнее.
Паттерны: async actions, selectors, persist
Асинхронные действия. В RTK — createAsyncThunk или RTK Query. В Zustand — просто async-функция:
// Zustand
const useUsersStore = create<UsersStore>((set) => ({
users: [],
loading: false,
fetchUsers: async () => {
set({ loading: true });
const res = await fetch('/api/users');
set({ users: await res.json(), loading: false });
},
}));
RTK Query даёт кеширование, инвалидацию, polling из коробки. У Zustand для этого нужен TanStack Query или SWR рядом.
Selectors. Zustand — selector прямо в хуке, компонент ре-рендерится только при изменении выбранного поля:
const users = useUsersStore((s) => s.users);
Persist. Zustand — через middleware persist:
import { persist } from 'zustand/middleware';
const useSettingsStore = create<SettingsStore>()(
persist(
(set) => ({
theme: 'dark',
setTheme: (t: string) => set({ theme: t }),
}),
{ name: 'settings-storage' }
)
);
В RTK — через redux-persist с дополнительной конфигурацией (persistReducer, persistGate, blacklist/whitelist).
Чеклист выбора
Выбирай Zustand, если:
- Проект небольшой или средний (до 10-15 сторов)
- Команда маленькая (1-5 человек), нет нужды в строгих конвенциях
- Критичен размер бандла (виджеты, микрофронтенды)
- Состояние простое: UI-флаги, формы, кеш данных
- Уже используешь TanStack Query для серверного состояния
Выбирай Redux Toolkit, если:
- Большая команда (5+ человек) — RTK навязывает единый стиль
- Сложная бизнес-логика с цепочками side-effects
- Нужен RTK Query для data fetching с кешированием
- Критична отладка: time-travel, запись сессий
- Проект долгоживущий (3+ лет) — экосистема Redux стабильнее
- Уже есть Redux — миграция на RTK проще, чем переезд на Zustand
Гибридный подход тоже работает: RTK Query для серверного кеша + Zustand для UI-состояния. Они не конфликтуют в одном приложении.
Не выбирай инструмент по хайпу. Zustand модный и минималистичный, но на проекте с 50 разработчиками его свобода превращается в хаос. Redux «тяжёлый», но его предсказуемость — то, за что платят в enterprise. Оцени команду, масштаб и горизонт — ответ придёт сам.