/ Nuxt

Как настроить Axios в приложении Nuxt

Вы, вероятно, слышали про axios или использовали его в своих веб-приложениях. Axios - это HTTP-клиент для браузера и node.js. Он значительно упрощает работу с API-запросами. Если вы работаете с Nuxt, есть официальный модуль, который ещё больше упрощает задачу интеграции этой библиотеки в фреймворк: @nuxtjs/axios. Именно на нём я сосредоточусь в этой статье. Предполагается, что вы знакомы с Nuxt и уже настроили проект. Я не буду подробно рассказывать о том, как использовать axios, об этом вы можете почитать в другой статье. Здесь вы узнаете, как настроить axios для ваших нужд в приложении Nuxt.

Как установить модуль axios

В вашем текущем проекте Nuxt запустите yarn add @nuxtjs/axios или npm install @nuxtjs/axios в зависимости от вашей рабочей среды.

Добавьте @nuxtjs/axios в список модулей в nuxt.config.js.

Теперь axios готов к использованию!

Базовое использование

Теперь вы можете использовать axios в ваших компонентах и в любой части приложения, которая имеет доступ к контексту Nuxt. Модуль добавляет axios в контекст и он становится доступен под именем $axios. Например, вы можете использовать this.$axios.get(url) или this.$axios.post(url, data) в любом .vue файле.

Настройка axios с помощью плагина

Одним из способов настройки axios является создание плагина, в котором задаются все значения по умолчанию. Это то же самое, что и создание любого другого плагина для Nuxt. Код плагина запускается до инициализации ядра Vue.

Создание плагина

  • Создайте файл в папке plugins. Назовите его как угодно, но, я советую назвать axios.js - это общепринятое название.
  • Добавить файл в списке плагинов в nuxt.config.js свойство plugins.
  • Готово!

Настройка плагина

Как же должен выглядеть этот плагин?

export default function ({ $axios, store }, inject) {
    // тут будем всё настраивать
})

В этой статье мы будем использовать только $axios и store из контекста. Но список параметров в действительности намного больше. Рекомендую просмотреть документацию по контексту Nuxt, где приведён список всех доступных параметров и их описание.

Вот несколько примеров того, что вы можете сделать в файле плагина plugins/axios.js:

  • Установить базовый URL для всех запросов
  • Создать несколько экземпляры axios, внедрить их в приложение и использовать в нужных местах необходимые экземпляры
  • Прикрепить токен к каждому запросу
  • Перехватывать ответ до того, как он попадает в вызываемый код приложения

Установка базового URL для всех запросов

Если все запросы направлены на один и тот же API, то можем задать базовый URL по умолчанию, чтобы в запросах к API мы не хардкодили домен, и в случае чего, могли в любой момент хост на другой. Мы можем настроить экземпляр axios так, чтобы он хранил этот базовый URL.

Это означает, что нам не нужно прописывать полный URL в каждом запросе, который мы хотим сделать. Просто добавьте это в функцию плагина:

$axios.setBaseUrl('https://api.badcode.ru/')

Теперь при использовании $axios этот URL всегда будет использоваться в качестве базового URL-адреса. Что даёт теперь возможным сделать такой вызов api:

$axios.get('/post/1')

Добавление нового экземпляра axios и внедрение его в приложение

Но что, если нам потребуется обращаться к нескольким доменам разных API? Вы можете создать новый экземпляр axios с любым именем, которое вы предпочитаете, и внедрить его в приложение.

Допустим, мы хотим получить данные о постах блога и пользователях, которые хостятся на разных API. Мы можем создать два разных экземпляра axios с разными базовыми адресами.

const postsApi = $axios.create()
const membersApi = $axios.create()

postsApi.setBaseUrl('https://api.badcode.ru/')
membersApi.setBaseUrl('https://members.badcode.ru/')

inject('postsApi', postsApi)
inject('membersApi', membersApi)

Здесь мы используем функция inject, предоставляемый плагинами Nuxt. Inject принимает два аргумента: первый - ключ, второй - значение.

То есть, после вызова функции inject, в контексте приложения Nuxt появится новое свойство с таким ключом и значением как было указано. Nuxt автоматически добавляет знак доллара к внедряемому ключу.

Чтобы использовать экземпляры axios, которые мы создали, вы можете обратиться так:

this.$membersApi.get('/people/1')
this.$postsApi.get('/posts/1')

Всё это упрощает использование и делает более явным то, что вы запрашиваете. Созданные нами экземпляры axios имеют те же вспомогательные функции, что и исходный экземпляр $axios.

Добавление токена в заголовок при каждом запросе

Если ваши API вызовы требуют какого-то токена авторизации, это также можно настроить в файле плагина. Чтобы установить заголовок авторизации в запросе, мы должны задать его в параметре option.

Допустим, для примера, API информации о пользователях блога (membersApi) требует аутентификации.
Вот один из способов установить Authorization токен в axios:

this.$membersApi.get('/people/1', {
    headers: {
        Authorization: `Bearer ${token}`,
    },
})

Этот код отлично работает, но быстро надоедает, когда приходится добавлять его в несколько мест. С помощью модуля @nuxtjs/axios мы можем указать добавление токена в запрос в файле плагина.

Если мы хотим использовать токен Bearer, мы можем поступить следующим образом:

const token = 'test_token'
$axios.setToken(token, 'Bearer')

Это добавит токен в заголовок под названием Authorization. Обычно этот токен хранится в localstorage или в хранилище Vuex. Я использую для хранения токена текущего пользователя Vuex state. В функции плагина у вас есть доступ к Vuex из контекста Nuxt.

Теперь можем проверить, добавляется ли токен в запрос к созданному экземпляру axios.

const token = store.state.currentUser.token
membersApi.setToken(token, 'Bearer')

Если вы используете refresh-токен или обновляете текущий токен каким-либо способом, вы также можете вызвать метод setToken, в том месте, где обновляется токен пользователя. В компоненте или модуле Vuex store вы можете, например, выполнить:

this.$membersApi.setToken(newToken, 'Bearer')

Перехват ответа axios

Если вы хотите проверять статус ответа при каждом вызове axios, вы можете зарегистрировать глобальный перехватчик респонсов.

@nuxtjs/axios предоставляет вспомогательные методы для этого. Допустим, мы хотим логировать что-то определённое каждый раз, когда статус ответа равен 404. Это можно реализовать с помощью метода onResponse.

$axios.onResponse((response) => {
    if (response.status === 404) {
        console.log('И вот он, 404 код')
    }
})

Итоговый файл плагина axios

В заключение, полный файл плагина (/plugins/axios.js) со всей конфигурацией, упомянутой в этой статье, может выглядеть примерно так:

export default function ({ $axios, store }, inject) {
    const postsApi = $axios.create()
    const membersApi = $axios.create()

    postsApi.setBaseUrl('https://api.badcode.ru/')
    membersApi.setBaseUrl('https://members.badcode.ru/')

    const token = store.state.currentUser.token
    membersApi.setToken(token, 'Bearer')

    membersApi.onResponse((response) => {
        if (response.status === 404) {
            console.log('И вот он, 404 код')
        }
    })

    inject('postsApi', postsApi)
    inject('membersApi', membersApi)
}

Внедрение зависимости axios-клиента в сервис

Очень часто возникает задача - создать класс, решающий определённые задачи, при работе с API. И в таких сервисах всегда нужен HTTP-клиент. Мы могли бы подключить axios простым импортом в нужном классе, но это не совсем то, что нам нужно.

Идеально было бы в конструктор передавать HTTP-клиент, являющийся абстракцией определённого интерфейса. В результате чего, в каком-то одном месте, мы могли бы подменять реализации HTTP-клиентов.

Или же проще, когда нам нужно просто получить инстанс axios, который создан с помощью плагина (настроены перехватчики, базовый URL и т.д.). Но при обычном импорте мы получаем совершенно другой инстанс. Потому, в этой секции я покажу, как передавать axios в конструктор в качестве зависимости в проекте Nuxt.

Прежде всего, аналогично добавлению плагина axios, нам нужно создать новый плагин, в котором мы будем объявлять все наши сервисы приложения (читай контейнер). Каждому из сервисов могут потребоваться различные зависимости, будь то API клиент для запросов, библиотека сохранения данных в cookie/localStorage.

Потому, для примера, создадим plugins/services.js с таким содержимым:

import PostService from "~/Services/Blog/PostService";
import FavoriteService from "~/Services/Catalog/FavoriteService";
import ConfigService from "~/Services/Shared/ConfigService";

// $cookies - это сторонняя библиотека по работе с cookie (https://www.npmjs.com/package/cookie-universal-nuxt)
export default ({ app: { $axios, $cookies } }, inject) => {
  // как зависимость передаём экземпляр axios
  inject('postService', new PostService($axios));
  inject('favoriteService', new FavoriteService($cookies));
  
  // как зависимость передаём экземпляр axios и библиотеку $cookies 
  inject('configService', new ConfigService($axios, $cookies));
}

Затем, в файле nuxt.config нужно подключить созданный плагин.

plugins: [
    '~/plugins/axios',
    '~/plugins/services.js',
  ],

И после чего, в контексте приложения Nuxt появятся зарегистрированные в плагине сервисы. Вызвать которые можно несколькими способами:

  • через переменную контекста ({ route, redirect, $postService, $configService, store })
  • в любом компоненте, или Vuex хранилище - this.$favoriteService.add(productId), this.$configService.getParams()

Резюме

Это был всего лишь краткий обзор того, как можно настроить axios для лучшей разработки приложения на Nuxt.js. Вы можете сделать намного больше и наверняка сможете отрефакторить этот кода и написать идеальный плагин для своих целей.

В этой статье так же было показано, как перехватывать ответ в axios. Так же, разобрались как внедрять зависимости в виде плагина axios в собственные классы.

Надеюсь, вы нашли эту статью полезной.