Twind интеграция

Fresh — это современный фреймворк для разработки веб-приложений на основе Deno, ориентированный на максимальную производительность, нативный рендеринг на сервере и минимизацию клиентской нагрузки. Его ключевое отличие от других JavaScript-фреймворков заключается в принципе no runtime JavaScript, где большая часть логики выполняется на сервере, а клиент получает оптимизированный HTML с минимальным JS.

Архитектура и принципы работы

Fresh использует islands architecture: страница рендерится сервером полностью, а интерактивные элементы («острова») подгружаются на клиент только при необходимости. Это снижает объем загружаемого JavaScript и ускоряет первую отрисовку (First Contentful Paint).

Основные элементы Fresh:

  • Роуты — каждый файл в папке routes соответствует URL. Например, routes/index.tsx/.
  • Файлы компонентов — используются для рендеринга отдельных частей интерфейса. Компоненты могут быть интерактивными islands или обычными статическими.
  • Handlers — функции, обрабатывающие запросы на сервере. Позволяют получать данные перед рендерингом страницы.
  • Signals и state — минимальные реактивные конструкции для управления состоянием islands.

Работа с компонентами

Компоненты в Fresh создаются с использованием JSX или TSX:

/** @jsx h */
import { h } from "preact";

export default function Counter() {
  let count = 0;
  return (
    <button onCl ick={() => count++}>
      Clicked {count} times
    </button>
  );
}

Если компонент требуется интерактивным на клиенте, он помечается директивой client.ts:

import Counter from "../components/Counter.client.tsx";

export default function Page() {
  return <Counter />;
}

Получение данных на сервере

Fresh использует функцию handler для серверной логики:

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

export const handler: Handlers = {
  async GET(req, ctx) {
    const data = await fetch("https://api.example.com/data").then(res => res.json());
    return ctx.render(data);
  }
};

Данные, возвращаемые через ctx.render, передаются компоненту страницы в пропсах.

Подключение CSS

Fresh поддерживает модули CSS, встроенные через import или сторонние утилиты вроде Tailwind/Twind. Основной способ стилизации — встроенные классы в JSX.


Twind интеграция с Fresh

Twind — это легковесный JIT CSS-инструмент для Tailwind, позволяющий генерировать стили на лету без сборки. Интеграция с Fresh позволяет использовать классы Tailwind прямо в компонентах без внешнего сборщика.

Установка и настройка

  1. Установка пакета Twind:
deno install -Af --unstable https://deno.land/x/twind@v1.7.0/mod.ts
  1. Создание конфигурации twind.config.ts:
import { defineConfig } from "twind";

export default defineConfig({
  theme: {
    extend: {
      colors: {
        primary: "#1DA1F2",
        secondary: "#14171A",
      },
    },
  },
});
  1. Инициализация Twind в Fresh-приложении:
import { setup } from "twind";
import config from "./twind.config.ts";

setup(config);

Эта настройка позволяет использовать классы прямо в JSX:

export default function Button() {
  return (
    <button class="bg-primary text-white px-4 py-2 rounded hover:bg-secondary">
      Click me
    </button>
  );
}

Серверная рендеринг CSS

Twind поддерживает серверный рендеринг (SSR) в Fresh. Для этого используется функция getStyleTag из twind/server:

import { getStyleTag } from "twind/server.ts";

export default function Page() {
  const styles = getStyleTag();
  return (
    <>
      <head dangerouslySetInnerHTML={{ __html: styles }} />
      <div class="text-primary p-4">Привет, Fresh + Twind!</div>
    </>
  );
}

Такой подход гарантирует, что CSS генерируется на сервере и сразу вставляется в HTML, минимизируя FOUC (Flash of Unstyled Content).

Динамические классы

Twind позволяет создавать классы динамически:

const size = "lg";
return <div class={`p-4 ${size === "lg" ? "text-xl" : "text-sm"}`}>Текст</div>;

Это делает стили полностью программируемыми и гибкими, в отличие от статической генерации Tailwind.

Оптимизация

  • Использование islands совместно с Twind уменьшает клиентский JavaScript, так как CSS уже встроен в HTML.
  • JIT-компиляция генерирует только используемые классы, что снижает общий вес стилей.
  • Fresh + Twind полностью исключает необходимость в сложных сборщиках вроде Webpack или Vite.

Рекомендации по структуре проекта

  • routes/ — маршруты страниц.
  • components/ — переиспользуемые компоненты и islands.
  • islands/ — интерактивные элементы, которые загружаются клиентом.
  • twind.config.ts — конфигурация стилей.
  • static/ — статические ресурсы (изображения, шрифты).

Поддержание такой структуры обеспечивает чистоту кода и оптимальное использование SSR и Twind одновременно.


Fresh с Twind предоставляет современный подход к разработке веб-приложений: быстрый серверный рендеринг, интерактивные islands, минимальный клиентский JavaScript и гибкая генерация CSS на лету. Такая комбинация подходит для производительных и современных приложений с масштабируемой архитектурой.