Fresh — это современный веб-фреймворк для JavaScript и TypeScript, ориентированный на создание высокопроизводительных приложений с минимальной нагрузкой на клиентскую часть. В основе Fresh лежит принцип Zero JavaScript Overhead, что означает отсутствие необходимости в традиционном бандлинге и минимальное количество JavaScript на клиенте. Fresh использует Deno в качестве среды выполнения, что обеспечивает нативную поддержку TypeScript и модульной системы без конфигурации.
Ключевыми особенностями являются:
Проект 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.
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, что упрощает поддержку больших проектов.
Fresh полностью поддерживает TypeScript без дополнительной настройки.
Файлы .ts и .tsx компилируются нативно через
Deno. Это позволяет использовать строгую типизацию, интерфейсы и
generics, повышая надежность кода.
Fresh оптимизирован под быструю доставку страниц:
Производительность измеряется через встроенные инструменты и легко масштабируется на Vercel, Deno Deploy и других платформах.
Fresh отличается от традиционных SPA и SSR-фреймворков, таких как Next.js или Nuxt, минимальной нагрузкой на клиент и отсутствием необходимости в сложном бандлинге. Архитектура Islands делает его идеальным выбором для приложений, где важна скорость загрузки и SEO, при этом сохраняя возможность интерактивности на клиенте.