Альтернативные платформы

Fresh — это современный веб-фреймворк для JavaScript и TypeScript, ориентированный на создание высокопроизводительных приложений с минимальной нагрузкой на клиентскую часть. В основе Fresh лежит принцип Zero JavaScript Overhead, что означает отсутствие необходимости в традиционном бандлинге и минимальное количество JavaScript на клиенте. Fresh использует Deno в качестве среды выполнения, что обеспечивает нативную поддержку TypeScript и модульной системы без конфигурации.

Ключевыми особенностями являются:

  • Islands architecture — концепция частичной гидратации, когда интерактивные компоненты загружаются на страницу только по мере необходимости.
  • SSR по умолчанию — все страницы рендерятся на сервере, что улучшает производительность и SEO.
  • Роутинг без конфигурации — маршруты создаются через структуру папок, аналогично Next.js.

Структура проекта

Проект Fresh имеет простую и интуитивную структуру:

/routes
/islands
/components
/static
/main.ts
  • /routes — папка с маршрутами. Каждый файл или папка соответствует URL.
  • /islands — интерактивные компоненты, которые могут содержать клиентский JavaScript.
  • /components — обычные компоненты UI без интерактивности.
  • /static — статические файлы, доступные по прямым URL.
  • main.ts — точка входа приложения.

Роутинг и обработка запросов

Каждый файл в /routes экспортирует функцию по стандарту Handler, которая управляет серверным рендерингом страницы:

import { Handlers } from "$fresh/server.ts";

export const handler: Handlers = {
  GET(req, ctx) {
    return ctx.render({ message: "Привет, Fresh!" });
  }
};

Метод ctx.render() передает данные в компонент страницы. Этот подход упрощает управление состоянием на сервере и уменьшает дублирование кода.

Динамические маршруты создаются с использованием квадратных скобок в имени файла:

/routes/posts/[id].tsx

Параметры URL доступны через ctx.params.

Islands architecture

Fresh использует концепцию Islands, когда большая часть страницы рендерится на сервере, а JavaScript подключается только к интерактивным элементам. Такой подход снижает количество загружаемого клиентского кода и улучшает производительность.

Пример интерактивного компонента в /islands:

/** @jsx h */
import { h } from "preact";
import { useState } from "preact/hooks";

export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onCl ick={() => setCount(count + 1)}>
      Нажато {count} раз
    </button>
  );
}

На странице компонент подключается так:

import Counter from "../islands/Counter.tsx";

export default function Home() {
  return (
    <div>
      <h1>Главная</h1>
      <Counter />
    </div>
  );
}

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

Управление состоянием и взаимодействие с сервером

Для передачи данных с сервера в компоненты используется объект props, передаваемый через ctx.render(). Для асинхронных операций можно использовать встроенные API маршрутов, обрабатывающие HTTP-запросы, что упрощает архитектуру без необходимости в сторонних state management библиотеках.

Пример API маршрута:

// /routes/api/data.ts
import { Handlers } from "$fresh/server.ts";

export const handler: Handlers = {
  GET() {
    return new Response(JSON.stringify({ value: 42 }), {
      headers: { "Content-Type": "application/json" },
    });
  }
};

Компонент может получать данные через fetch:

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

export default function DataFetcher() {
  const [data, setData] = useState<number | null>(null);

  useEffect(() => {
    fetch("/api/data")
      .then(res => res.json())
      .then(json => setData(json.value));
  }, []);

  return <div>Данные: {data}</div>;
}

Работа со статикой и ресурсами

Папка /static позволяет размещать изображения, шрифты и другие ресурсы, доступные по прямым URL. Файлы копируются без изменений и не участвуют в бандлинге. Для импорта стилей используется стандартный CSS или CSS Modules, что упрощает поддержку больших проектов.

Типизация и интеграция с TypeScript

Fresh полностью поддерживает TypeScript без дополнительной настройки. Файлы .ts и .tsx компилируются нативно через Deno. Это позволяет использовать строгую типизацию, интерфейсы и generics, повышая надежность кода.

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

Fresh оптимизирован под быструю доставку страниц:

  • SSR минимизирует время до первого байта.
  • Partial hydration снижает нагрузку на клиентский JavaScript.
  • Эффективный роутинг без бандлинга ускоряет навигацию.

Производительность измеряется через встроенные инструменты и легко масштабируется на Vercel, Deno Deploy и других платформах.

Сравнение с другими платформами

Fresh отличается от традиционных SPA и SSR-фреймворков, таких как Next.js или Nuxt, минимальной нагрузкой на клиент и отсутствием необходимости в сложном бандлинге. Архитектура Islands делает его идеальным выбором для приложений, где важна скорость загрузки и SEO, при этом сохраняя возможность интерактивности на клиенте.