REST API интеграция

SvelteKit предоставляет удобный и современный способ работы с REST API благодаря встроенной поддержке fetch и серверных маршрутов. Ключевым аспектом является разделение работы с API на клиентскую и серверную части, что позволяет оптимизировать производительность и безопасно обрабатывать данные.

Клиентская интеграция

Для обращения к REST API на клиенте используется стандартный fetch. Основная структура запроса выглядит следующим образом:

<script>
  import { onMount } from 'svelte';
  let data = [];
  let error = null;

  onMount(async () => {
    try {
      const response = await fetch('/api/posts');
      if (!response.ok) throw new Error('Ошибка при загрузке данных');
      data = await response.json();
    } catch (e) {
      error = e.message;
    }
  });
</script>

{#if error}
  <p>{error}</p>
{:else}
  <ul>
    {#each data as post}
      <li>{post.title}</li>
    {/each}
  </ul>
{/if}

Особенности:

  • onMount гарантирует, что запрос выполняется только после загрузки компонента.
  • Проверка response.ok обязательна для корректного управления ошибками.
  • JSON-ответ автоматически преобразуется в объект с помощью response.json().

Серверная интеграция через SvelteKit endpoints

SvelteKit позволяет создавать API-эндпоинты на сервере с расширением .ts или .js внутри папки src/routes. Пример:

// src/routes/api/posts/+server.js
import { json } from '@sveltejs/kit';

export async function GET() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts');
  const posts = await res.json();
  return json(posts);
}

Преимущества серверного подхода:

  • Возможность скрыть ключи API или токены.
  • Предварительная обработка данных перед отправкой клиенту.
  • Легкость кэширования и оптимизации производительности.

Работа с POST, PUT, DELETE запросами

Для создания или изменения данных используется метод POST или PUT. Пример POST-запроса через серверный endpoint:

// src/routes/api/posts/+server.js
import { json } from '@sveltejs/kit';

export async function POST({ request }) {
  const body = await request.json();
  const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body)
  });
  const result = await response.json();
  return json(result, { status: 201 });
}

Ключевые моменты:

  • request.json() преобразует тело запроса в объект.
  • Указание Content-Type: application/json необходимо для корректной передачи данных.
  • Возврат с status: 201 указывает на успешное создание ресурса.

Обработка ошибок и таймаутов

Для стабильной работы приложения важно правильно обрабатывать ошибки:

async function fetchWithTimeout(url, options, timeout = 5000) {
  const controller = new AbortController();
  const id = setTimeout(() => controller.abort(), timeout);
  options.signal = controller.signal;

  try {
    const response = await fetch(url, options);
    if (!response.ok) throw new Error(`Ошибка: ${response.status}`);
    return await response.json();
  } finally {
    clearTimeout(id);
  }
}

Преимущества подхода:

  • Прерывание зависших запросов предотвращает зависание интерфейса.
  • Удобная обработка сетевых и серверных ошибок.

Интеграция с SvelteKit stores

Для централизованного хранения данных от REST API рекомендуется использовать Svelte stores:

// src/stores/posts.js
import { writable } from 'svelte/store';

export const posts = writable([]);

export async function loadPosts() {
  try {
    const res = await fetch('/api/posts');
    if (!res.ok) throw new Error('Не удалось загрузить посты');
    posts.set(await res.json());
  } catch (e) {
    console.error(e);
  }
}

Преимущества:

  • Данные доступны в любом компоненте через подписку на store.
  • Обновления автоматически отражаются в интерфейсе.

Роутинг и динамические параметры

SvelteKit позволяет создавать динамические API-маршруты:

// src/routes/api/posts/[id]/+server.js
import { json } from '@sveltejs/kit';

export async function GET({ params }) {
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
  if (!res.ok) return json({ error: 'Пост не найден' }, { status: 404 });
  const post = await res.json();
  return json(post);
}

Особенности:

  • params содержит все динамические сегменты URL.
  • Позволяет строить RESTful архитектуру с минимальными усилиями.

Асинхронная оптимизация и параллельные запросы

Для ускорения загрузки нескольких ресурсов одновременно применяются Promise.all:

const [users, posts] = await Promise.all([
  fetch('/api/users').then(r => r.json()),
  fetch('/api/posts').then(r => r.json())
]);

Преимущества:

  • Экономия времени за счёт параллельного выполнения.
  • Простая интеграция в компоненты и stores.

Кэширование и SvelteKit hooks

SvelteKit предоставляет handle в hooks.server.js для глобальной обработки запросов и кэширования ответов:

// src/hooks.server.js
export async function handle({ event, resolve }) {
  const response = await resolve(event, { ssr: true });
  response.headers.set('Cache-Control', 'max-age=60');
  return response;
}

Применение:

  • Ускорение повторных запросов.
  • Контроль над сроком жизни кэшированных данных.

Эти подходы позволяют выстраивать гибкую, безопасную и масштабируемую интеграцию REST API в SvelteKit-приложениях, используя преимущества как клиентской, так и серверной стороны, с удобной обработкой данных, ошибок и кэширования.