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

Fresh — это фреймворк для Deno, построенный вокруг идеи минимализма, серверного рендеринга и отсутствия шага сборки. Структура проекта играет ключевую роль: она не просто организует файлы, а напрямую определяет поведение приложения. Маршруты, острова интерактивности, статические ресурсы и конфигурация связываются через соглашения, а не через сложные настройки.

Проект Fresh обычно создаётся с помощью deno run -A -r https://fresh.deno.dev, после чего формируется предсказуемая и строгая иерархия каталогов.


Корень проекта

В корне располагаются файлы и папки, определяющие глобальное поведение приложения:

  • main.ts Точка входа приложения. Здесь инициализируется сервер Fresh, подключается конфигурация и запускается обработка HTTP-запросов.

  • fresh.gen.ts Автоматически сгенерированный файл. Содержит реестр маршрутов, островов и middleware. Редактирование вручную недопустимо — файл пересобирается при изменениях структуры.

  • deno.json или deno.jsonc Конфигурация Deno: импорты, разрешения, задачи (tasks). Используется вместо package.json.

  • import_map.json (опционально) Карта импортов для сокращения путей и управления зависимостями.


Каталог routes/

Ключевой элемент структуры Fresh. Каждый файл или папка внутри routes/ напрямую соответствует URL-пути.

Принцип соответствия:

  • routes/index.tsx/
  • routes/about.tsx/about
  • routes/blog/[id].tsx/blog/123

Файлы маршрутов

Файл маршрута экспортирует HTTP-обработчики (GET, POST и т.д.) или компонент страницы по умолчанию.

export default function Page() {
  return <h1>Hello Fresh</h1>;
}

Также допустима комбинация серверной логики и JSX:

export const handler = {
  GET(req, ctx) {
    return ctx.render({ time: Date.now() });
  },
};

export default function Page(props) {
  return <p>{props.data.time}</p>;
}

Динамические сегменты

  • [param].tsx — одиночный параметр
  • [...slug].tsx — rest-параметр (несколько сегментов)

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


Специальные файлы маршрутов

Fresh поддерживает ряд соглашений, расширяющих поведение маршрутов:

  • _app.tsx Оборачивает все страницы. Используется для глобальной разметки, подключения CSS, метатегов.

  • _layout.tsx Применяется к группе маршрутов в пределах каталога. Позволяет создавать вложенные layout’ы.

  • _middleware.ts Серверный middleware, выполняемый до обработчика маршрута. Подходит для аутентификации, логирования, модификации ответа.


Каталог islands/

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

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

  • Только файлы из islands/ попадают в клиентский JavaScript.
  • Острова подключаются явно внутри JSX страниц.
  • Остальной код остаётся серверным и не увеличивает размер бандла.
import Counter from "../islands/Counter.tsx";

export default function Page() {
  return <Counter />;
}

Каждый остров — обычный Preact-компонент, но с возможностью использовать состояние, эффекты и обработчики событий.


Каталог components/

Непривязанные к маршрутам UI-компоненты. В отличие от islands/, компоненты из components/ не гидратируются автоматически и остаются серверными.

Используются для:

  • шаблонов
  • UI-блоков без интерактивности
  • композиции страниц

Такое разделение позволяет строго контролировать клиентскую нагрузку.


Каталог static/

Хранилище статических файлов, доступных напрямую по URL:

  • изображения
  • шрифты
  • иконки
  • CSS-файлы
  • robots.txt, favicon и т.п.

Файл static/logo.png будет доступен по адресу /logo.png.


Каталог styles/ (необязательный)

Не является частью ядра Fresh, но часто используется для хранения глобальных стилей, CSS-модулей или preflight-стилей. Подключение происходит через _app.tsx.


Серверная логика и утилиты

Часто создаются дополнительные каталоги:

  • lib/ или utils/ — вспомогательные функции
  • services/ — работа с API, базами данных
  • db/ — инициализация хранилищ и моделей

Эти каталоги не имеют специального значения для Fresh, но логично отделяют бизнес-логику от представления.


Генерация и роль fresh.gen.ts

Файл fresh.gen.ts связывает структуру файлов с рантаймом. Он содержит:

  • список маршрутов
  • регистрацию островов
  • middleware

Fresh отслеживает изменения в проекте и автоматически обновляет этот файл. Он необходим для корректной работы сервера и горячей перезагрузки.


Принцип «структура = поведение»

В Fresh отсутствует сложная маршрутизация, конфигурационные DSL и ручная регистрация компонентов. Поведение приложения выводится напрямую из структуры проекта:

  • расположение файла определяет URL
  • каталог определяет вложенность layout’ов
  • размещение в islands/ определяет клиентскую интерактивность

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


Масштабирование структуры

При росте приложения структура остаётся стабильной:

  • маршруты группируются каталогами
  • layout’ы вложены логически
  • интерактивность локализована в островах
  • серверная логика вынесена из UI

Fresh поощряет архитектуру, где структура файлов — основной источник истины, а не побочный артефакт настроек.