Українська

Дізнайтеся про API unstable_cache в Next.js для детального контролю кешування даних, покращуючи продуктивність та досвід користувача в динамічних застосунках.

Нестабільний кеш Next.js: детальний контроль кешування для динамічних застосунків

Next.js здійснив революцію у веброзробці, пропонуючи потужні функції для створення продуктивних та масштабованих застосунків. Однією з його ключових переваг є надійний механізм кешування, який дозволяє розробникам оптимізувати завантаження та рендеринг даних для кращого досвіду користувача. Хоча Next.js надає різні стратегії кешування, API unstable_cache пропонує новий рівень детального контролю, дозволяючи розробникам налаштовувати поведінку кешування відповідно до конкретних потреб їхніх динамічних застосунків. У цій статті ми розглянемо API unstable_cache, його можливості, переваги та практичне застосування.

Розуміння кешування в Next.js

Перш ніж заглиблюватися в unstable_cache, важливо зрозуміти різні рівні кешування в Next.js. Next.js використовує декілька механізмів кешування для підвищення продуктивності:

Хоча ці механізми кешування є потужними, вони не завжди можуть забезпечити необхідний рівень контролю для складних, динамічних застосунків. Саме тут на допомогу приходить unstable_cache.

Представляємо API `unstable_cache`

API unstable_cache в Next.js дозволяє розробникам визначати власні стратегії кешування для окремих операцій завантаження даних. Він надає детальний контроль над:

API вважається "нестабільним", оскільки він все ще знаходиться в розробці та може зазнати змін у майбутніх версіях Next.js. Однак він пропонує цінну функціональність для розширених сценаріїв кешування.

Як працює `unstable_cache`

Функція unstable_cache приймає два основні аргументи:

  1. Функція, яка завантажує або обчислює дані: Ця функція виконує фактичне отримання або обчислення даних.
  2. Об'єкт опцій: Цей об'єкт визначає параметри кешування, такі як TTL, теги та ключ.

Ось базовий приклад використання unstable_cache:

import { unstable_cache } from 'next/cache';

async function getData(id: string) {
  return unstable_cache(
    async () => {
      // Симулюємо завантаження даних з API
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const data = { id: id, value: `Data for ID ${id}` };
      return data;
    },
    ["data", id],
    { tags: ["data", `item:${id}`] }
  )();
}

export default async function Page({ params }: { params: { id: string } }) {
  const data = await getData(params.id);
  return 
{data.value}
; }

У цьому прикладі:

Ключові особливості та опції `unstable_cache`

1. Час життя (Time-to-Live, TTL)

Опція revalidate (раніше `ttl` у попередніх експериментальних версіях) вказує максимальний час (у секундах), протягом якого кешовані дані вважаються дійсними. Після цього часу кеш ревалідується при наступному запиті.

import { unstable_cache } from 'next/cache';

async function getData(id: string) {
  return unstable_cache(
    async () => {
      // Симулюємо завантаження даних з API
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const data = { id: id, value: `Data for ID ${id}` };
      return data;
    },
    ["data", id],
    { tags: ["data", `item:${id}`], revalidate: 60 } // Кешувати на 60 секунд
  )();
}

У цьому прикладі дані будуть кешуватися протягом 60 секунд. Через 60 секунд наступний запит ініціює ревалідацію, завантажуючи свіжі дані з API та оновлюючи кеш.

Загальна рекомендація: Встановлюючи значення TTL, враховуйте частоту оновлення даних. Для даних, що часто змінюються, доцільно використовувати коротший TTL. Для відносно статичних даних довший TTL може значно підвищити продуктивність.

2. Теги кешу

Теги кешу дозволяють групувати пов'язані кешовані дані та інвалідувати їх колективно. Це корисно, коли оновлення одного елемента даних впливає на інші пов'язані дані.

import { unstable_cache, revalidateTag } from 'next/cache';

async function getProduct(id: string) {
  return unstable_cache(
    async () => {
      // Симулюємо завантаження даних про продукт з API
      await new Promise((resolve) => setTimeout(resolve, 500));
      const product = { id: id, name: `Product ${id}`, price: Math.random() * 100 };
      return product;
    },
    ["product", id],
    { tags: ["products", `product:${id}`] }
  )();
}

async function getCategoryProducts(category: string) {
  return unstable_cache(
    async () => {
      // Симулюємо завантаження продуктів за категорією з API
      await new Promise((resolve) => setTimeout(resolve, 500));
      const products = Array.from({ length: 3 }, (_, i) => ({ id: `${category}-${i}`, name: `Product ${category}-${i}`, price: Math.random() * 100 }));
      return products;
    },
    ["categoryProducts", category],
    { tags: ["products", `category:${category}`] }
  )();
}

// Інвалідувати кеш для всіх продуктів та конкретного продукту
async function updateProduct(id: string, newPrice: number) {
  // Симулюємо оновлення продукту в базі даних
  await new Promise((resolve) => setTimeout(resolve, 500));

  // Інвалідувати кеш для продукту та категорії продуктів
  revalidateTag("products");
  revalidateTag(`product:${id}`);

  return { success: true };
}

У цьому прикладі:

Загальна рекомендація: Використовуйте значущі та послідовні імена тегів. Розгляньте можливість створення стратегії тегування, яка відповідає вашій моделі даних.

3. Генерація ключа кешу

Ключ кешу використовується для ідентифікації кешованих даних. За замовчуванням unstable_cache генерує ключ на основі аргументів, переданих у функцію. Однак ви можете налаштувати процес генерації ключа, використовуючи другий аргумент `unstable_cache`, який є масивом, що діє як ключ. Коли будь-який з елементів у масиві змінюється, кеш інвалідується.

import { unstable_cache } from 'next/cache';

async function getData(userId: string, sortBy: string) {
  return unstable_cache(
    async () => {
      // Симулюємо завантаження даних з API
      await new Promise((resolve) => setTimeout(resolve, 1000));
      const data = { userId: userId, sortBy: sortBy, value: `Data for user ${userId}, sorted by ${sortBy}` };
      return data;
    },
    [userId, sortBy],
    { tags: ["user-data", `user:${userId}`] }
  )();
}

У цьому прикладі ключ кешу базується на параметрах userId та sortBy. Це гарантує, що кеш буде інвалідовано при зміні будь-якого з цих параметрів.

Загальна рекомендація: Переконайтеся, що ваша стратегія генерації ключів кешу є послідовною та враховує всі відповідні фактори, що впливають на дані. Розгляньте можливість використання хеш-функції для створення унікального ключа зі складних структур даних.

4. Ручна ревалідація

Функція `revalidateTag` дозволяє вручну інвалідувати кеш для даних, пов'язаних з певними тегами. Це корисно, коли вам потрібно оновити кеш у відповідь на події, які не викликані безпосередньо запитом користувача, наприклад, фонове завдання або вебхук.

import { revalidateTag } from 'next/cache';

async function handleWebhook(payload: any) {
  // Обробляємо дані вебхука

  // Інвалідуємо кеш для пов'язаних даних
  revalidateTag("products");
  revalidateTag(`product:${payload.productId}`);
}

Загальна рекомендація: Використовуйте ручну ревалідацію стратегічно. Надмірна інвалідація може звести нанівець переваги кешування, тоді як недостатня інвалідація може призвести до застарілих даних.

Практичні випадки використання `unstable_cache`

1. Динамічний контент з нечастими оновленнями

Для вебсайтів з динамічним контентом, який не змінюється дуже часто (наприклад, дописи в блозі, статті новин), ви можете використовувати unstable_cache з довшим TTL для кешування даних на тривалий період. Це зменшує навантаження на ваш бекенд та покращує час завантаження сторінок.

2. Дані, специфічні для користувача

Для даних, специфічних для користувача (наприклад, профілі користувачів, кошики для покупок), ви можете використовувати unstable_cache з ключами кешу, що включають ідентифікатор користувача. Це гарантує, що кожен користувач бачить свої власні дані і що кеш інвалідується при зміні даних користувача.

3. Дані в реальному часі з допустимістю застарілих даних

Для застосунків, що відображають дані в реальному часі (наприклад, курси акцій, стрічки соціальних мереж), ви можете використовувати unstable_cache з коротким TTL для забезпечення оновлень майже в реальному часі. Це збалансовує потребу в актуальних даних з перевагами кешування для продуктивності.

4. A/B тестування

Під час A/B тестування важливо кешувати варіант експерименту, призначений користувачеві, щоб забезпечити послідовний досвід. `unstable_cache` можна використовувати для кешування вибраного варіанту, використовуючи ID користувача як частину ключа кешу.

Переваги використання `unstable_cache`

Рекомендації та найкращі практики

`unstable_cache` проти кешування `fetch` API

Next.js також надає вбудовані можливості кешування через fetch API. За замовчуванням Next.js автоматично кешує результати запитів fetch. Однак unstable_cache пропонує більшу гнучкість та контроль, ніж кешування `fetch` API.

Ось порівняння двох підходів:

Функція `unstable_cache` `fetch` API
Контроль над TTL Явно налаштовується за допомогою опції revalidate. Неявно керується Next.js, але можна вплинути за допомогою опції revalidate в параметрах fetch.
Теги кешу Підтримує теги кешу для інвалідації пов'язаних даних. Немає вбудованої підтримки тегів кешу.
Налаштування ключа кешу Дозволяє налаштовувати ключ кешу за допомогою масиву значень, які використовуються для його побудови. Обмежені можливості налаштування. Ключ генерується з URL-адреси запиту.
Ручна ревалідація Підтримує ручну ревалідацію за допомогою revalidateTag. Обмежена підтримка ручної ревалідації.
Гранулярність кешування Дозволяє кешувати окремі операції завантаження даних. В основному зосереджено на кешуванні HTTP-відповідей.

Загалом, використовуйте кешування `fetch` API для простих сценаріїв завантаження даних, де стандартна поведінка кешування є достатньою. Використовуйте unstable_cache для складніших сценаріїв, де вам потрібен детальний контроль над поведінкою кешування.

Майбутнє кешування в Next.js

API unstable_cache є важливим кроком уперед у можливостях кешування Next.js. По мірі розвитку API ми можемо очікувати ще потужніших функцій та більшої гнучкості в управлінні кешуванням даних. Слідкувати за останніми розробками в кешуванні Next.js є вирішальним для створення високопродуктивних та масштабованих застосунків.

Висновок

API unstable_cache від Next.js пропонує розробникам безпрецедентний контроль над кешуванням даних, дозволяючи їм оптимізувати продуктивність та досвід користувача в динамічних застосунках. Розуміючи особливості та переваги unstable_cache, ви можете використовувати його потужність для створення швидших, більш масштабованих та чутливих вебастосунків. Не забувайте ретельно продумувати свою стратегію кешування, вибирати відповідні значення TTL, ефективно проєктувати ключі кешу та відстежувати продуктивність кешу для досягнення оптимальних результатів. Відкрийте для себе майбутнє кешування в Next.js та розкрийте повний потенціал ваших вебастосунків.