Розробка фронтенду dApp на Nuxt.js

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка фронтенду dApp на Nuxt.js
Середній
~1-2 тижні
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1306
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1218
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    920
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1147
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    610
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    885

Розробка фронтенда dApp на Nuxt.js

Vue-екосистема у Web3 програє React за кількістю готових бібліотек, але не за можливостями. Основна складність — більшість Web3 tooling написано React-first: wagmi, ConnectKit, RainbowKit працюють тільки з React. Для Nuxt потрібен або інший стек, або обёртки. Розберемо, що реально працює в 2024-2025.

Web3-стек для Nuxt 3

Підключення гаманців

@wagmi/core + @web3modal/wagmi — wagmi core працює без React, Vue-обёртка @wagmi/vue з'явилась у wagmi v2. Web3Modal підтримує Vue через окремий пакет @web3modal/wagmi/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 бібліотеки несумісні з SSR: звертаються до window, localStorage, ethereum інжектору.

viem для читання даних з блокчейну — працює в будь-якому окруженні:

// composables/useContract.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] }
  )
}

SSR-специфіка

Nuxt 3 за замовчуванням використовує SSR, і це створює тертя з Web3:

Проблема hydrationwindow.ethereum існує тільки в браузері. Будь-який компонент, який читає стан гаманця, повинен бути або в <ClientOnly>, або перевіряти process.client:

<template>
  <ClientOnly>
    <WalletButton />
    <template #fallback>
      <button disabled>Загрузка...</button>
    </template>
  </ClientOnly>
</template>

Nuxt plugin з ssr: false — альтернатива <ClientOnly>:

// nuxt.config.ts
export default defineNuxtConfig({
  plugins: [
    { src: '~/plugins/wagmi.client.ts', mode: 'client' }
  ]
})

useNuxtApp().$wagmi — після інічіалізації в плагіні wagmi config доступний через Nuxt's provide/inject паттерн.

Composables для Web3

Різниця між React hooks та Vue composables у контексті Web3: Vue реактивність через ref/computed краще працює для derived state, який змінюється при зміні аккаунту або мережі.

// 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 }
}

Трансакції та стан

Управління статусом трансакції — типовий pain point. wagmi v2 надає useWriteContract + useWaitForTransactionReceipt:

const { writeContract, data: hash } = useWriteContract()
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash })

Паттерн для UI: показуємо три стани — "підпишіть у гаманці", "трансакція відправлена (hash)", "підтверджена". Nuxt + 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

Строки розробки фронтенда dApp на Nuxt — 1-2 тижні в залежності від складності: базове підключення гаманця та читання контрактів займає 3-4 дні, повноцінний dApp з кількома екранами, трансакціями та обробкою помилок — 1-1.5 тижні.