Fresh — современный веб-фреймворк для JavaScript и TypeScript, ориентированный на работу с Deno и серверной рендерингом. Он построен вокруг минималистичной архитектуры, где основной упор сделан на скорость и прямое управление DOM без лишнего промежуточного кода. Приложения Fresh рендерятся на сервере, а интерактивные компоненты подключаются по мере необходимости, что позволяет достигать высокой производительности.
Проект Fresh имеет стандартную структуру каталогов:
Каждый маршрут представляет собой функцию, возвращающую JSX, аналогично React. Использование TypeScript позволяет строго типизировать данные и предотвращать большинство ошибок на этапе компиляции.
Маршруты в Fresh могут быть как статическими, так и динамическими.
Динамический маршрут создается через квадратные скобки в имени файла,
например: routes/posts/[id].tsx.
Пример обработчика:
import { Handlers } from "$fresh/server.ts";
export const handler: Handlers = {
GET(req, ctx) {
const { id } = ctx.params;
return new Response(`Пост с ID: ${id}`);
},
};
Обработчики поддерживают все стандартные HTTP-методы: GET, POST, PUT,
DELETE. Контекст ctx содержит параметры маршрута, куки и
данные сессий, что позволяет реализовать сложную серверную логику без
использования внешних библиотек.
Islands — ключевая концепция Fresh для добавления интерактивности. Они позволяют загружать только ту часть UI, которая требует клиентских скриптов, снижая время загрузки страницы и нагрузку на браузер.
Пример интерактивного компонента:
/** @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>
);
}
Fresh интегрируется с внешними API и базами данных через стандартные
JavaScript-инструменты. Для получения данных на сервере используются
функции типа fetch и прямые обращения к базе через
клиентские драйверы. Принцип Server-Side Rendering
гарантирует, что все данные рендерятся на сервере до отправки HTML, что
улучшает SEO и ускоряет первый рендер.
Пример запроса к API:
export const handler: Handlers = {
async GET(req, ctx) {
const res = await fetch("https://api.example.com/posts");
const posts = await res.json();
return ctx.render({ posts });
},
};
Fresh не навязывает конкретной библиотеки для стилей. Чаще всего используются Tailwind CSS или чистый CSS. Для обеспечения цветового контраста и доступности следует придерживаться следующих принципов:
Пример использования CSS-переменных для цветового контраста:
:root {
--primary-color: #1e40af; /* темно-синий */
--secondary-color: #fef3c7; /* светло-желтый */
--text-color: #111827; /* темный текст */
}
button {
background-color: var(--primary-color);
color: var(--secondary-color);
border: none;
padding: 0.5rem 1rem;
cursor: pointer;
}
button:hover {
background-color: #1e3a8a;
}
Использование переменных позволяет легко адаптировать интерфейс под разные темы и контролировать контраст для доступности пользователей с нарушениями зрения.
Fresh ориентирован на минимизацию размера клиентских бандлов. Для этого:
Fresh полностью совместим с TypeScript, что позволяет создавать типобезопасные маршруты, компоненты и обработчики данных. Использование интерфейсов и типов предотвращает большинство ошибок на этапе компиляции и повышает надежность приложений.
Пример типизации props компонента:
interface ButtonProps {
label: string;
onClick: () => void;
}
export default function Button({ label, onClick }: ButtonProps) {
return <button onCl ick={onClick}>{label}</button>;
}
Fresh поддерживает стандартные методы тестирования через Deno:
superoak для
эмуляции HTTP-запросов.Эта структура позволяет покрывать код тестами на всех уровнях, сохраняя при этом простоту и производительность приложения.