Для начала работы с Fresh требуется установленный Deno версии 1.36 или выше. Fresh использует встроенные возможности Deno, такие как импорт модулей по URL и встроенный TypeScript, что позволяет обойтись без дополнительной сборки. Создание нового проекта выполняется через команду:
deno run -A https://fresh.deno.dev my-app
Эта команда создаёт структуру проекта с базовыми директориями:
routes, components, static и
конфигурационным файлом deno.json.
Ключевой момент — Fresh полностью ориентирован на серверный рендеринг
с автоматическим генератором маршрутов. Любой файл .tsx в
папке routes автоматически становится маршрутом.
Fresh использует JSX/TSX синтаксис для описания компонентов. Форматирование кода и компонентов играет критическую роль для поддерживаемости и читаемости проекта.
Пример базового компонента:
export default function Home() {
return (
<main class="p-4 max-w-2xl mx-auto">
<h1 class="text-3xl font-bold mb-6">Привет, Fresh!</h1>
<p class="text-gray-700">Это серверно-рендеринговое приложение с Deno.</p>
</main>
);
}
Ключевые моменты форматирования:
<Component
propOne="value"
propTwo={true}
propThree={someFunction()}
/>
Fresh использует файловую маршрутизацию. Динамические параметры обозначаются квадратными скобками в названии файла:
routes/
└─ blog/
└─ [id].tsx
Внутри компонента доступ к параметрам осуществляется через объект
params:
import { Handlers } from "$fresh/server.ts";
export const handler: Handlers = {
GET(req, ctx) {
const { id } = ctx.params;
return ctx.render({ postId: id });
},
};
export default function BlogPost({ data }: { data: { postId: string } }) {
return <div>Пост с ID: {data.postId}</div>;
}
Форматирование кода в таких случаях требует четкого разделения логики обработки запроса и рендеринга компонента. Логика должна быть максимально компактной, чтобы JSX оставался легко читаемым.
Fresh автоматически поддерживает Tailwind через конфигурацию
tailwind.config.js. Для больших страниц рекомендуется
использовать:
<button class="bg-blue-500 hover:bg-blue-600 text-white font-semibold py-2 px-4 rounded">
Нажми меня
</button>
Фокус на читаемость: длинные цепочки классов выравниваются по вертикали при превышении 80–100 символов:
<div class="
p-6
max-w-lg
mx-auto
bg-white
shadow-md
rounded-lg
">
Контент
</div>
Handlers в Fresh должны быть компактными и читаемыми. Структура:
import { Handlers } from "$fresh/server.ts";
export const handler: Handlers = {
GET(req, ctx) {
const data = fetchData();
return ctx.render({ data });
},
};
function fetchData() {
return [
{ id: 1, title: "Первый элемент" },
{ id: 2, title: "Второй элемент" },
];
}
export default function List({ data }: { data: { id: number; title: string }[] }) {
return (
<ul>
{data.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
}
Рекомендации по форматированию:
Для больших приложений важно поддерживать единый стиль:
Следует поддерживать единую систему именования файлов и компонентов, использовать PascalCase для компонентов и camelCase для переменных и функций.
Islands — ключевая особенность Fresh. Они позволяют подключать интерактивный JavaScript к серверно-рендеренным страницам без полного SPA:
import Counter from "../islands/Counter.tsx";
export default function Page() {
return (
<main class="p-4">
<h1>Счётчик</h1>
<Counter start={0} />
</main>
);
}
Форматирование Islands:
export default function Counter({ start }: { start: number }) {
const [count, setCount] = useState(start);
return (
<button
class="px-4 py-2 bg-green-500 text-white rounded"
onCl ick={() => setCount(count + 1)}
>
{count}
</button>
);
}
Правильное форматирование и организация кода в Fresh обеспечивает масштабируемость проекта, удобство поддержки и высокую читаемость.