Fresh — это современный подход к разработке веб-приложений на JavaScript, основанный на принципах минимизации состояния на сервере и использовании нативных возможностей браузера для рендеринга интерфейса. Основная идея заключается в том, чтобы каждая страница была максимально легковесной, изолированной и мгновенно загружаемой без излишней зависимости от клиентского фреймворка.
Fresh часто применяется в сочетании с серверным рендерингом (SSR), где сервер генерирует HTML на основе текущего запроса, а клиент получает готовый контент без необходимости дополнительных запросов к API для первичной загрузки страницы. Это уменьшает время до первого отображения (Time To First Paint) и повышает производительность приложений.
Архитектура Fresh строится вокруг нескольких ключевых компонентов:
Маршруты (Routes) Каждый маршрут соответствует определённому URL и отвечает за генерацию HTML для этого URL. В отличие от традиционных SPA, где клиент скачивает один большой бандл и управляет маршрутизацией, Fresh создаёт маршруты как отдельные сущности на сервере.
Изолированные компоненты Компоненты Fresh — это отдельные единицы интерфейса, которые могут быть рендерены на сервере или клиенте по мере необходимости. Они не требуют глобального состояния и взаимодействуют только через props или параметры маршрута.
Автоматическая оптимизация Fresh автоматически разделяет код на чанки, подгружая только то, что необходимо для конкретной страницы. Это снижает объём JavaScript на клиенте и ускоряет загрузку.
В Fresh маршруты организуются по файловой структуре проекта. Каждый
файл в папке routes соответствует конкретному пути. Пример
структуры:
routes/
├── index.js
├── about.js
├── blog/
│ ├── index.js
│ └── [id].js
index.js отвечает за корневой путь /.about.js — за путь /about.blog содержит вложенные маршруты, где
[id].js обозначает динамический сегмент URL.Динамические маршруты автоматически получают параметр
id, который можно использовать для генерации страницы,
например, загрузки конкретной статьи из базы данных.
Fresh позволяет передавать данные в компонент маршрута через функцию
handler или getData. Основная идея —
сервер подготавливает все данные до отправки HTML
клиенту. Пример:
export async function handler(req, ctx) {
const postId = ctx.params.id;
const post = await fetchPostFromDB(postId);
return ctx.render({ post });
}
ctx.params.id — параметр динамического маршрута.ctx.render — функция, которая рендерит компонент с
переданными данными.На клиенте компонент получает props напрямую, что исключает необходимость дополнительного запроса к API для первичной загрузки страницы.
Для крупных приложений маршруты можно группировать по функциональным зонам, создавая вложенные папки. Например:
routes/
├── dashboard/
│ ├── index.js
│ ├── settings.js
│ └── users/
│ ├── index.js
│ └── [userId].js
/dashboard — главная панель./dashboard/settings — настройки пользователя./dashboard/users/[userId] — профиль конкретного
пользователя.Группировка маршрутов упрощает поддержку кода, обеспечивает логическую структуру проекта и позволяет применять общие middleware или layout для группы маршрутов.
Fresh поддерживает middleware на уровне маршрутов и групп маршрутов. Middleware выполняется перед рендерингом страницы и может:
Пример middleware для группы маршрутов:
export function middleware(req, ctx) {
if (!req.user) {
return Response.redirect("/login");
}
return ctx.next();
}
ctx.next() — передача управления следующему обработчику
или маршруту.Для групп маршрутов часто используют общие layout-компоненты, которые оборачивают содержимое всех страниц группы. Это позволяет:
Пример layout для группы dashboard:
export default function DashboardLayout({ children, user }) {
return (
<div>
<Sidebar user={user} />
<main>{children}</main>
</div>
);
}
Каждый маршрут внутри dashboard использует этот layout
автоматически, что упрощает поддержку интерфейса.
Fresh интегрирует кэширование на уровне маршрутов и компонентов. Возможности включают:
Благодаря этим механизмам страницы остаются быстрыми, даже если приложение содержит десятки или сотни маршрутов.
Fresh сочетает в себе удобство SPA и производительность традиционных SSR-приложений, обеспечивая современную архитектуру для масштабируемых веб-приложений.