Кастомный useFetch в Nuxt
В Nuxt часто делают фронтенд и ходят во внешнее API — удобно задать опции по умолчанию для всех запросов к нему.
Утилита $fetch (её использует useFetch) намеренно не настраивается глобально: так поведение запросов в приложении остаётся предсказуемым, а модули и интеграции могут опираться на ядро.
При этом Nuxt позволяет создать свой fetch-клиент под ваш API (или несколько, если API несколько).
Рецепт: API-клиент с авторизацией
Допустим, внешнее API на https://api.nuxt.com требует JWT через nuxt-auth-utils, а при ответе 401 нужно перенаправлять на /login.
export const useAPI = createUseFetch({
baseURL: 'https://api.nuxt.com',
onRequest ({ options }) {
const { session } = useUserSession()
if (session.value?.token) {
options.headers.set('Authorization', `Bearer ${session.value.token}`)
}
},
async onResponseError ({ response }) {
if (response.status === 401) {
await navigateTo('/login')
}
},
})
Теперь каждый вызов useAPI добавляет заголовок авторизации и обрабатывает 401:
<script setup lang="ts">
const { data: profile } = await useAPI('/me')
const { data: orders } = await useAPI('/orders')
</script>
Рецепт: свой экземпляр $fetch
Если нужен более низкоуровневый контроль, создайте экземпляр $fetch в плагине Nuxt и используйте его с useAsyncData или передайте в createUseFetch.
$fetch — настроенный экземпляр ofetch: можно задать базовый URL сервера Nuxt и вызывать функции напрямую при SSR (без лишнего HTTP).export default defineNuxtPlugin((nuxtApp) => {
const { session } = useUserSession()
const api = $fetch.create({
baseURL: 'https://api.nuxt.com',
onRequest ({ request, options, error }) {
if (session.value?.token) {
options.headers.set('Authorization', `Bearer ${session.value?.token}`)
}
},
async onResponseError ({ response }) {
if (response.status === 401) {
await nuxtApp.runWithContext(() => navigateTo('/login'))
}
},
})
return {
provide: {
api,
},
}
})
Дальше можно вызывать свой $fetch напрямую:
<script setup>
const { $api } = useNuxtApp()
const { data: modules } = await useAsyncData('modules', () => $api('/modules'))
</script>
useAsyncDataизбегает двойной загрузки данных при SSR (сервер и клиент при гидрации).