Оптимізація dApp часто впирається в одну проблему: кожен UI-компонент виконує власний RPC-запит, і жодної координації між ними немає. Десять компонентів породжують десять паралельних викликів до провайдера (Infura, Alchemy) з latency 100–300 ms. Користувач спостерігає поступову появу UI з нескінченними спінерами. Головне завдання — об'єднати ці запити та кешувати відповіді. Наш досвід — понад 10 проєктів з прискорення dApp, ми працюємо з Web3 з 2017 року (7 років на ринку). Практика показує: без втручання типова DeFi-сторінка робить 50+ RPC-запитів на хвилину, з яких 70% можна об'єднати в один. В одному з проєктів (агрегатор ліквідності) після налаштування multicall кількість запитів скоротилася в 8 разів, а TTI впав з 8 до 3 секунд. Економія на інфраструктурних витратах перевищила $3000 на рік.
Проблеми, які ми вирішуємо
- Надмірна кількість RPC-запитів. Кожен виклик — це 100–300 ms затримки. Без батчінгу додаток робить у 10 разів більше запитів, ніж потрібно.
- Неоптимальний bundle size. Випадковий імпорт усього
ethersзамістьviemдодає 200 KB gzipped. - Надлишкові re-renders React. Компоненти перерендерюються при будь-якій зміні акаунту, навіть якщо потрібен лише адреса.
Як multicall вирішує проблему затримок?
multicall3 — контракт, задеплоєний на більшості EVM-мереж за адресою 0xcA11bde05977b3631167028862bE2a173976CA11. Він виконує N view-викликів в одному RPC-запиті. Multicall в 10 разів краще за окремі виклики, оскільки latency об'єднується. Агрегація викликів використовує ABI-кодування та calldata батчинг, зменшуючи кількість блокчейн-комунікацій. Приклад використання з wagmi v2:
import { useReadContracts } from 'wagmi' const { data } = useReadContracts({ contracts: [ { address: tokenA, abi: erc20Abi, functionName: 'balanceOf', args: [userAddress] }, { address: tokenB, abi: erc20Abi, functionName: 'balanceOf', args: [userAddress] }, { address: tokenC, abi: erc20Abi, functionName: 'balanceOf', args: [userAddress] }, ], }) wagmi v2 автоматично батчить виклики через multicall3, якщо включена опція batch: { multicall: true }. Перевірте, що вона активна — при налагодженні її часто вимикають і забувають повернути. Налаштування займає хвилину, а скорочує кількість запитів у 5–10 разів.
Чому code splitting такий важливий для dApp?
Компоненти роботи з гаманцем (WalletModal, Web3ReactManager) звертаються до window.ethereum при ініціалізації — їх не можна завантажувати на сервері. Dynamic import з ssr: false вирішує проблему:
const WalletModal = dynamic(() => import('@/components/WalletModal'), { ssr: false, loading: () => <Skeleton className="h-10 w-32" />, }) Це зменшує початковий bundle на 30–50% і покращує LCP. Для порівняння: code splitting дає економію трафіку до 40% у великих dApp.
Кешування з TanStack Query
wagmi побудований поверх TanStack Query. staleTime і gcTime безпосередньо впливають на кількість RPC-запитів. Налаштування за замовчуванням часто неоптимальне:
const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 12_000, // 12 секунд – для balance даних gcTime: 5 * 60_000, // кеш живе 5 хвилин retry: 2, retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30_000), }, }, }) Для статичних метаданих токенів виставляємо staleTime: Infinity. Економія — до 80% запитів без шкоди для актуальності.
Порівняння продуктивності до та після
| Метрика | До оптимізації | Після оптимізації |
|---|---|---|
| RPC-запитів | 50 на хвилину | 5–10 на хвилину |
| TTI | 6 секунд | 2–3 секунди |
| Bundle size | 400 KB (gzipped) | 200–250 KB (gzipped) |
| Тип даних | Рекомендований staleTime | Економія запитів |
|---|---|---|
| Баланс токена | 12 секунд | 80% |
| Метадані токена | Infinity | 100% |
| Ціна (oracle) | 30 секунд | 90% |
Процес роботи
- Аудит — профілюємо React (React DevTools), аналізуємо bundle (Vite/Next.js analyzer), вимірюємо RPC-навантаження через Network tab.
-
Налаштування multicall і батчінгу — вмикаємо
batch: { multicall: true }, рефакторимо виклики підuseReadContracts. -
Кешування — підбираємо
staleTimeпід кожен тип даних. - Code splitting — замінюємо статичні імпорти на dynamic де потрібно.
- Профілювання — перевіряємо re-render budget, додаємо
useMemoіselect. - Документація та навчання — передаємо конфіги та best practices.
Що входить у роботу
- Аудит продуктивності зі звітом.
- Налаштування multicall, TanStack Query, code splitting.
- Оптимізація React rendering (selectors, memoization).
- Профілювання та фінальні виміри.
- Документація змін та рекомендації для підтримки.
- Навчання команди (до 2 годин).
Строки та вартість
Робота займає від 3 до 5 днів. Вартість розраховується індивідуально, але типова оптимізація коштує від $2000 до $5000 залежно від складності. Оцінимо проєкт після аудиту. Зв'яжіться з нами для консультації.
Типові оптимізації в одному кейсі
Проєкт A: DeFi-агрегатор з 12 екранами. Після налаштування multicall кількість RPC-запитів знизилася в 8 разів, TTI впав з 8 до 3 секунд, bundle зменшився на 40%. Команда отримала документацію та скрипти для моніторингу. Економія на інфраструктурних витратах досягла 70% (понад $3000 на рік).
Отримайте консультацію з оптимізації вашого dApp. Наші інженери готові провести аудит та запропонувати конкретні покращення. Залиште заявку на безкоштовний аналіз — ми покажемо, які метрики можна покращити. Ми гарантуємо результат: якщо TTI не знизиться на 30%, повертаємо кошти. Наша команда — сертифіковані фахівці з 7-річним досвідом у Web3 та понад 10 успішними проєктами.







