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

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

Реактивные данные и кэш

Во Vue.js все данные компонентов являются реактивными. Это означает, что любые изменения состояния автоматически отражаются в DOM. Для кэширования запросов реактивные свойства часто используются совместно с объектами ref или reactive.

import { ref } from 'vue';

export default {
  setup() {
    const dataCache = ref(null);
    const loading = ref(false);

    const fetchData = async () => {
      if (dataCache.value) return dataCache.value; // Возврат из кэша
      loading.value = true;
      const response = await fetch('https://api.example.com/data');
      dataCache.value = await response.json();
      loading.value = false;
      return dataCache.value;
    }

    return { dataCache, loading, fetchData };
  }
}

В этом примере данные сохраняются в dataCache после первого запроса. Повторные вызовы fetchData используют кэшированное значение, если оно доступно.

Использование Vuex для глобального кэширования

Vuex позволяет хранить состояние приложения централизованно. Кэширование запросов на уровне Vuex особенно полезно для данных, используемых в нескольких компонентах.

// store.js
import { createStore } from 'vuex';

export const store = createStore({
  state() {
    return {
      itemsCache: {}
    }
  },
  mutations: {
    setCache(state, { key, data }) {
      state.itemsCache[key] = data;
    }
  },
  actions: {
    async fetchItems({ state, commit }, key) {
      if (state.itemsCache[key]) return state.itemsCache[key];
      const response = await fetch(`https://api.example.com/items/${key}`);
      const data = await response.json();
      commit('setCache', { key, data });
      return data;
    }
  }
});

Использование Vuex для кэширования позволяет обращаться к одним и тем же данным из разных компонентов без повторных сетевых запросов.

Кэширование с помощью сторонних библиотек

Для более сложного кэширования можно использовать библиотеки, такие как Axios с интерцепторами или SWR/vue-query. Пример с Axios:

import axios from 'axios';

const cache = {};

axios.interceptors.request.use(config => {
  const key = config.url;
  if (cache[key]) {
    config.adapter = () => {
      return Promise.resolve({
        data: cache[key],
        status: 200,
        statusText: 'OK',
        headers: {},
        config
      });
    }
  }
  return config;
});

axios.interceptors.response.use(response => {
  cache[response.config.url] = response.data;
  return response;
});

Такой подход позволяет автоматически кэшировать все запросы и возвращать данные из кэша без изменения логики компонентов.

Локальное хранилище и IndexedDB

Для долговременного кэширования можно использовать localStorage или IndexedDB. Это актуально для данных, которые должны сохраняться между перезагрузками страницы:

const cacheKey = 'usersData';

async function fetchUsers() {
  const cached = localStorage.getItem(cacheKey);
  if (cached) return JSON.parse(cached);

  const response = await fetch('https://api.example.com/users');
  const data = await response.json();
  localStorage.setItem(cacheKey, JSON.stringify(data));
  return data;
}

Использование локального хранилища позволяет быстро загружать данные при последующих визитах без необходимости обращения к серверу.

Стратегии кэширования

  • Cache-first: сначала проверяется кэш, только при его отсутствии выполняется запрос.
  • Network-first: сначала выполняется сетевой запрос, кэш используется как резерв.
  • Stale-while-revalidate: возвращается кэшированное значение, одновременно обновляя данные с сервера для последующих обращений.

Выбор стратегии зависит от характера данных. Для редко меняющейся информации предпочтителен cache-first, а для динамических данных — stale-while-revalidate.

Реактивное обновление кэша

Важно поддерживать актуальность кэша. В Vue.js это достигается с помощью реактивных свойств:

import { reactive } from 'vue';

const state = reactive({
  postsCache: {}
});

async function fetchPost(id) {
  if (!state.postsCache[id]) {
    const response = await fetch(`https://api.example.com/posts/${id}`);
    state.postsCache[id] = await response.json();
  }
  return state.postsCache[id];
}

Любые изменения state.postsCache автоматически обновляют компоненты, которые используют эти данные.

Оптимизация памяти и сброс кэша

При использовании кэша необходимо контролировать размер хранимых данных. Для этого можно реализовать TTL (time-to-live) или ограничение на количество элементов:

const cache = {};
const TTL = 60000; // 1 минута

function setCache(key, data) {
  cache[key] = { data, timestamp: Date.now() };
}

function getCache(key) {
  const cached = cache[key];
  if (!cached) return null;
  if (Date.now() - cached.timestamp > TTL) {
    delete cache[key];
    return null;
  }
  return cached.data;
}

Такой подход предотвращает накопление устаревших данных и снижает нагрузку на память.


Кэширование запросов во Vue.js сочетает реактивность, централизованное состояние и возможности внешних библиотек. Применение стратегий кэширования, контроль времени жизни данных и интеграция с Vuex или Axios позволяют создавать быстрые и отзывчивые интерфейсы, минимизируя количество сетевых обращений.