Маршрутизация на основе файловой системы

Fresh — это современный фреймворк для разработки веб-приложений на базе Deno. Одной из ключевых особенностей Fresh является маршрутизация на основе файловой системы. Это подход, при котором структура папок и файлов напрямую определяет маршруты приложения, упрощая навигацию и организацию кода.


Структура проекта и маршруты

В Fresh каждый файл в папке routes автоматически становится маршрутом. Стандартная структура выглядит так:

routes/
├── index.tsx
├── about.tsx
├── blog/
│   ├── index.tsx
│   └── [id].tsx
  • index.tsx в корне папки routes соответствует маршруту /.
  • about.tsx становится доступен по пути /about.
  • Папка blog с index.tsx формирует маршрут /blog.
  • Файл [id].tsx — динамический маршрут, позволяющий обрабатывать переменные сегменты URL, например /blog/123.

Динамические маршруты

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

export default function BlogPostPage({ params }: { params: { id: string } }) {
  return <h1>Пост блога {params.id}</h1>;
}

В этом примере params.id получает значение сегмента URL, соответствующего [id]. Это позволяет создавать страницы с контентом, загружаемым по идентификатору.

Catch-all маршруты

Для маршрутов с переменной глубиной вложенности используется синтаксис [...slug].tsx. Он захватывает все сегменты URL после определённого уровня:

export default function Page({ params }: { params: { slug: string[] } }) {
  return <div>Путь: {params.slug.join('/')}</div>;
}

Если URL /docs/2025/updatesparams.slug будет массивом ["2025", "updates"].


Обработка HTTP методов

Файлы маршрутов могут экспортировать функции для обработки конкретных HTTP методов: GET, POST, PUT, DELETE. Пример:

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

export const handler: Handlers = {
  GET(req, ctx) {
    return new Response("GET-запрос обработан");
  },
  POST(req, ctx) {
    return new Response("POST-запрос обработан");
  },
};

Это даёт возможность полностью управлять серверным поведением в рамках одного файла маршрута.


Интеграция компонентов и рендеринг

Маршруты Fresh используют JSX/TSX компоненты для рендеринга. Основной файл маршрута может возвращать JSX-разметку или вызывать другие компоненты:

export default function HomePage() {
  return (
    <main>
      <h1>Главная страница</h1>
      <p>Добро пожаловать в Fresh-приложение.</p>
    </main>
  );
}

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


Layouts и общие шаблоны

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

export default function BaseLayout({ children }: { children: React.ReactNode }) {
  return (
    <div>
      <header>Шапка сайта</header>
      <main>{children}</main>
      <footer>Футер сайта</footer>
    </div>
  );
}

Применение layout в маршрутах осуществляется через вложенные компоненты:

import BaseLayout from "../components/BaseLayout.tsx";

export default function AboutPage() {
  return (
    <BaseLayout>
      <h2>О проекте</h2>
      <p>Информация о сайте.</p>
    </BaseLayout>
  );
}

Навигация и ссылки

Для переходов между страницами используется компонент <a> или <Link> (если используется дополнительная библиотека для SPA-переходов). Fresh оптимизирует переходы, используя динамическую подгрузку страниц без полного обновления браузера.

<a href="/about">О проекте</a>

или с <Link>:

import { Link } from "$fresh/runtime.ts";

<Link href="/blog/123">Читать пост</Link>

Советы по организации маршрутов

  1. Ясная структура папок — папка routes должна отражать логику URL.
  2. Динамические маршруты — использовать [param].tsx для переменных сегментов.
  3. Catch-all маршруты[...slug].tsx для сложных иерархий URL.
  4. Повторяющиеся элементы — вынести в layout или компоненты для переиспользования.
  5. HTTP обработка — хранить логику API в соответствующих файлах маршрутов.

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