Nuxt: useFetch, useAsyncData, server routes

↑ 7.5 SSR и Nuxt · ← Предыдущая · → Следующая

Желательно~4 мин чтенияУровень: senior

Зачем это на собесе

Загрузка данных в SSR: главное — не делать запрос дважды и передать состояние клиенту.

useFetch и useAsyncData

<script setup lang="ts">
const { data: user, status, error, refresh } = await useFetch(`/api/users/${route.params.id}`, {
  key: `user-${route.params.id}`,
  server: true,
  lazy: false,
  watch: [() => route.params.id],
  transform: (u) => ({ ...u, name: u.name.trim() }),
})
 
const { data: stats } = await useAsyncData('stats', () => $fetch('/api/stats'))
</script>
  • useFetch(url) — сокращение для useAsyncData(key, () => $fetch(url));
  • на сервере запрос выполняется, результат сериализуется в payload страницы, клиент берёт его без повторного запроса;
  • lazy: true — не блокировать навигацию, показать состояние загрузки;
  • $fetch — чистая утилита без дедупликации и payload (для событий, POST-действий на клиенте).

Типичная ошибка: вызов $fetch в setup напрямую → запрос выполнится дважды (сервер и клиент).

Кэш и повторное использование

Ключ (key) дедуплицирует запросы; getCachedData управляет кэшем; refreshNuxtData('key'), clearNuxtData.

Общее состояние

const token = useState<string | null>('token', () => null)   // безопасно для SSR, переносится клиенту

Server routes (Nitro)

// server/api/users/[id].get.ts
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, 'id')
  const user = await db.users.find(id)
  if (!user) throw createError({ statusCode: 404, statusMessage: 'Not found' })
  return user
})
// server/api/orders.post.ts
export default defineEventHandler(async (event) => {
  const body = await readValidatedBody(event, orderSchema.parse)
  return await createOrder(body)
})

Применение: BFF (проксирование и агрегация бэкендов), скрытие секретов (ключи хранятся в runtimeConfig на сервере), обход CORS.

runtimeConfig

export default defineNuxtConfig({
  runtimeConfig: {
    apiSecret: '',                 // только сервер
    public: { apiBase: '' },       // доступно и клиенту
  },
})

Значения переопределяются переменными NUXT_API_SECRET, NUXT_PUBLIC_API_BASE во время выполнения.

Вопросы с ответами