Network debugging

Фреймворк Fresh для JavaScript строится на принципах быстрого рендеринга на сервере и минимизации клиентского JavaScript. Понимание работы сетевых запросов и умение их отлаживать является ключевым для разработки производительных веб-приложений на Fresh.

Серверные обработчики и маршруты

Fresh использует концепцию маршрутов, где каждый путь соответствует папке или файлу в каталоге routes. Серверная логика обрабатывается в handler-функциях, которые могут быть асинхронными:

export const handler = {
  async GET(req, ctx) {
    const data = await fetchExternalAPI();
    return new Response(JSON.stringify(data), {
      headers: { "Content-Type": "application/json" },
    });
  },
};

Ключевой момент — все сетевые запросы, выполняемые на сервере, проходят в момент рендеринга страницы. Это позволяет сразу получать актуальные данные, но требует контроля ошибок и таймаутов.

Логирование и отладка запросов

Для отладки запросов на сервере используют стандартный console.log, но важно сохранять структуру данных:

try {
  const response = await fetch("https://api.example.com/data");
  const json = await response.json();
  console.log("Ответ API:", json);
} catch (err) {
  console.error("Ошибка запроса:", err);
}

Логирование должно включать:

  • URL запроса и параметры;
  • статус-код ответа;
  • тело ответа;
  • ошибки сети и таймауты.

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

Клиентские запросы и useEffect

Хотя Fresh минимизирует клиентский JavaScript, иногда требуется динамическое обновление данных. Для этого используют стандартные хуки React:

import { useState, useEffect } from "preact/hooks";

export default function DataComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch("/api/data")
      .then(res => res.json())
      .then(setData)
      .catch(err => console.error("Ошибка клиентского запроса:", err));
  }, []);

  if (!data) return <p>Загрузка...</p>;
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

Важно следить за:

  • корректной обработкой ошибок;
  • повторными вызовами при изменении зависимостей;
  • синхронизацией данных с сервером.

Использование промежуточного слоя (middleware)

Fresh позволяет добавлять middleware для перехвата запросов и ответов. Это удобно для логирования, кэширования или изменения заголовков:

export const middleware = async (req, next) => {
  console.log("Запрос:", req.url);
  const response = await next();
  console.log("Статус ответа:", response.status);
  return response;
};

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

Работа с ошибками и таймаутами

Сетевые запросы могут завершаться ошибками из-за проблем сети, серверов или превышения лимитов времени. Для управления этим используют:

  • try/catch на сервере и клиенте;
  • ограничение времени ожидания через AbortController:
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch("https://api.example.com/data", {
    signal: controller.signal,
  });
  const data = await response.json();
} catch (err) {
  if (err.name === "AbortError") {
    console.error("Запрос прерван по таймауту");
  } else {
    console.error("Сетевая ошибка:", err);
  }
} finally {
  clearTimeout(timeout);
}

Такой подход предотвращает зависание страницы при долгих запросах.

Инструменты для отладки сетевого трафика

Для полноценной диагностики сетевых запросов можно использовать:

  • встроенные DevTools в браузере (вкладка Network);
  • curl или Postman для тестирования API отдельно от приложения;
  • логирование на сервере с сохранением тела запросов и ответов.

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

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

Для снижения нагрузки на сервер и ускорения отклика используют кэширование:

  • Cache-Control заголовки для статических данных;
  • серверное хранение результатов частых запросов;
  • использование IndexedDB или localStorage на клиенте для повторного использования данных.

Кэширование критично для приложений, где сетевые задержки могут влиять на UX.

Мониторинг производительности

Отладка сетевого слоя включает измерение времени отклика API. На сервере используют performance.now() или сторонние библиотеки:

const start = performance.now();
await fetchExternalAPI();
console.log("Время запроса:", performance.now() - start, "мс");

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

Сценарии сложных запросов

  • Параллельные запросы с Promise.all для ускорения загрузки данных:
const [users, posts] = await Promise.all([
  fetch("/api/users").then(r => r.json()),
  fetch("/api/posts").then(r => r.json()),
]);
  • Последовательные запросы с зависимостями:
const user = await fetch("/api/users/1").then(r => r.json());
const posts = await fetch(`/api/posts?userId=${user.id}`).then(r => r.json());
  • Обработка paginated API с циклами или рекурсией.

Эффективное управление этими сценариями снижает количество ошибок и повышает предсказуемость работы приложения.

Логирование на продакшене

На продакшене используют централизованные логирующие системы (например, Sentry или Logflare) для отслеживания сетевых ошибок, без засорения консоли. Логи включают:

  • URL и параметры запроса;
  • статус ответа;
  • тело ошибки;
  • временные метки.

Это позволяет быстро реагировать на сбои и поддерживать стабильность приложения.

Сетевое дебаггирование в Fresh объединяет строгий контроль на сервере, аккуратную работу с клиентскими запросами и инструментальные методы для мониторинга. Это создаёт основу для надежных и быстрых веб-приложений.