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

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка фронтенда dApp на Nuxt.js
Средняя
~1-2 недели
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1056
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка фронтенда 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 доступен через provide/inject паттерн Nuxt.

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 с несколькими экранами, транзакциями и обработкой ошибок — неделю-полторы.