Розробка фронтенду dApp на Nuxt.js
При розробці децентралізованих додатків на Vue-екосистемі ви швидко впираєтесь у несумісність популярних Web3-бібліотек з SSR. Wagmi, RainbowKit, ConnectKit — всі вони заточені під React. Однак для Nuxt 3 є робочі альтернативи, які дають не менший функціонал, а в деяких аспектах і перевершують React-рішення. Наша команда має 5+ років досвіду в blockchain-розробці та реалізувала понад 20 dApp на Vue і Nuxt. Ми гарантуємо стабільну роботу інтерфейсів навіть в умовах високого навантаження мережі.
Типова помилка новачків — намагатися використовувати Web3-бібліотеки безпосередньо на сервері. Це призводить до падіння додатку з window is not defined. Рішення — ізоляція клієнтських модулів, яку ми розглянемо нижче. Крім того, грамотна інтеграція гаманця з урахуванням SSR дозволяє заощадити до 40% часу на налагодження порівняно з чистим React-рішенням. Вартість такої доробки при міграції існуючого проекту варіюється залежно від складності, а повноцінний dApp на Nuxt окупається в короткостроковій перспективі за рахунок зниження витрат на підтримку. Зв'яжіться з нами для консультації — ми допоможемо вибрати оптимальний стек.
Як підключити гаманець у Nuxt 3?
Основний інструмент — зв'язка @wagmi/vue та @web3modal/wagmi. Wagmi v2 представив офіційну Vue-обгортку, що усунуло головний біль інтеграції. Наведемо налаштування плагіна:
// plugins/wagmi.client.ts import { createWeb3Modal } from '@web3modal/wagmi/vue' import { createConfig, http } from '@wagmi/vue' import { mainnet, arbitrum } from '@wagmi/vue/chains' import { walletConnect, injected } from '@wagmi/vue/connectors' export default defineNuxtPlugin(() => { const config = createConfig({ chains: [mainnet, arbitrum], connectors: [ walletConnect({ projectId: useRuntimeConfig().public.wcProjectId }), injected(), ], transports: { [mainnet.id]: http(), [arbitrum.id]: http(), }, }) createWeb3Modal({ wagmiConfig: config, projectId: useRuntimeConfig().public.wcProjectId, }) }) Плагін обов'язково позначаємо .client.ts, оскільки Web3-бібліотеки працюють тільки на стороні клієнта. Це критично для уникнення помилок гідратації.
Покрокова інструкція налаштування
- Встановіть пакети
@web3modal/wagmiта@wagmi/vue. - Створіть файл у
plugins/з розширенням.client.ts, як показано вище. - Додайте конфігурацію з потрібними мережами та коннекторами.
- Ініціалізуйте Web3Modal у тому ж плагіні.
- У компонентах використовуйте
useAccount,useConnectта інші композабли.
Чому SSR потребує особливого підходу?
Nuxt 3 за замовчуванням виконує рендеринг на сервері, де немає window, localStorage або ethereum. Якщо не ізолювати Web3-компоненти, додаток впаде з ReferenceError. Два типові рішення:
- Обгортка
<ClientOnly>— компонент рендериться тільки в браузері. Вміст всередині не потрапляє в серверний HTML, що ідеально для віджета гаманця. - Плагін з
mode: 'client'уnuxt.config.ts:
export default defineNuxtConfig({ plugins: [ { src: '~/plugins/wagmi.client.ts', mode: 'client' } ] }) Другий спосіб кращий для глобального конфігу — так він ініціалізується раніше, ніж компоненти. Порівняння: підхід з <ClientOnly> простіший для разових елементів, але для цілих сторінок краще використовувати плагін — він гарантує, що Web3-бібліотеки завантажаться до першого рендеру компонентів. Різниця в продуктивності може досягати 2-3 разів при складних макетах.
Що входить у розробку фронтенду dApp?
Ми пропонуємо повний цикл робіт: від аналізу вимог до деплою та підтримки. У стандартний пакет входить:
- Інтеграція гаманців (MetaMask, WalletConnect, Coinbase Wallet)
- Взаємодія зі смарт-контрактами (читання, запис, події)
- Обробка транзакцій (статуси, газ, помилки) — також ми оптимізуємо газові ліміти, знижуючи вартість транзакцій.
- SSR-оптимізація (ізоляція клієнтських модулів, кешування)
- Адаптивна верстка (Tailwind CSS / UnoCSS)
- Документація коду (коментарі, README)
- Передача доступів та навчання команди
Терміни — від 1 тижня на MVP до 3 тижнів на повноцінний додаток. Оцінимо ваш проект безкоштовно — просто напишіть нам.
Composables та управління станом
На відміну від React-хуків, Vue composables з ref та computed природно вписуються в реактивну парадигму. Приклад:
// composables/useWalletState.ts export const useWalletState = () => { const { address, isConnected, chain } = useAccount() const shortAddress = computed(() => address.value ? `${address.value.slice(0, 6)}...${address.value.slice(-4)}` : null ) const isWrongNetwork = computed(() => isConnected.value && chain.value?.id !== mainnet.id ) return { address, isConnected, shortAddress, isWrongNetwork } } Для глобального стану використовуємо Pinia — наприклад, для зберігання списку транзакцій та повідомлень.
Читання on-chain даних з viem
viem — універсальна бібліотека для читання блокчейну. Вона працює в будь-якому середовищі, включаючи серверний рендеринг. Приклад composable для отримання балансу USDC:
// composables/useTokenBalance.ts import { createPublicClient, http, parseAbi } from 'viem' import { mainnet } from 'viem/chains' const client = createPublicClient({ chain: mainnet, transport: http(), }) export const useTokenBalance = (address: Ref<`0x${string}` | undefined>) => { return useAsyncData( `balance-${address.value}`, () => address.value ? client.readContract({ address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', abi: parseAbi(['function balanceOf(address) view returns (uint256)']), functionName: 'balanceOf', args: [address.value], }) : Promise.resolve(0n), { watch: [address] } ) } Зверніть увагу на useAsyncData — він дає вбудований кеш та дедуплікацію запитів.
Транзакції та їх статуси
Для відправки транзакцій використовуємо useWriteContract та useWaitForTransactionReceipt з wagmi:
const { writeContract, data: hash } = useWriteContract() const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash }) Паттерн відображення: просимо підтвердити в гаманці → показуємо хеш з прогресом → підтвердження. Pinia зберігає стан для toast-повідомлень.
Зведена таблиця стеку
| Задача | Бібліотека |
|---|---|
| Framework | Nuxt 3 (Vue 3 + Vite) |
| Wallet connect | @web3modal/wagmi + @wagmi/vue |
| On-chain reads | viem PublicClient |
| State | Pinia |
| Styling | Tailwind CSS 3 / UnoCSS |
| Data fetching | useAsyncData + TanStack Query |
Додатково використовуємо Tenderly для симуляції транзакцій та Slither для статичного аналізу контрактів — це не входить у стандартний пакет, але може бути додано на запит. Як показано в документації Wagmi, інтеграція з Vue стала значно простішою.
Порівняння Nuxt vs React для dApp
| Параметр | Nuxt (Vue) | Next (React) |
|---|---|---|
| Швидкість розробки MVP | 2-3 дні | 3-5 днів |
| Кількість boilerplate | Мінімум (composables) | Значне (hooks + context) |
| SSR-адаптація | Проста (плагін .client) | Стандартна (dynamic import) |
| Інтеграція гаманців | Wagmi/Vue + Web3Modal | Wagmi + RainbowKit |
Nuxt виграє за рахунок лаконічності Vue та вбудованої ізоляції клієнтських модулів. Якщо у вас є React-проект на wagmi/ethers, міграція на Nuxt 3 потребує заміни React-хуків на Vue composables та додавання SSR-ізоляції. Однак Vue reactivity краще підходить для derived state (коротка адреса, перевірка мережі).
Зверніться до нас для консультації — ми допоможемо уникнути цих помилок і прискоримо розробку. Замовте розробку dApp на Nuxt сьогодні — отримайте прототип за 1 тиждень!







