Twind плагин

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

Структура проекта Fresh

Проект на Fresh имеет строгую организацию каталогов:

  • /routes — директория для маршрутов. Каждый файл или папка внутри этой директории соответствует URL в приложении. Файлы с расширением .tsx содержат компоненты страницы.
  • /islands — компоненты, которые рендерятся на клиенте. Это минимальные интерактивные части страницы, загружаемые асинхронно.
  • /static — статические ресурсы, доступные по прямому URL.
  • /components — общие UI-компоненты, не привязанные к конкретному маршруту.
  • /plugins — подключаемые расширения, такие как Twind.

Интеграция Twind

Twind — это утилитарный CSS-in-JS, который предоставляет возможность писать Tailwind-подобные стили прямо в JavaScript/TypeScript. Fresh поддерживает интеграцию с Twind через собственный плагин.

Установка Twind
deno install -A --unstable https://deno.land/x/fresh@latest/twind.ts
Настройка плагина

Создается файл twind.ts:

import { setup } from "https://cdn.skypack.dev/twind";
import { virtual } from "https://cdn.skypack.dev/twind/virtual";

setup({
  theme: {
    extend: {
      colors: {
        primary: "#1E40AF",
        secondary: "#9333EA",
      },
    },
  },
  plugins: {
    virtual,
  },
});

В этом примере:

  • theme.extend позволяет добавлять собственные цвета, размеры, шрифты.
  • plugins.virtual используется для динамического генерации CSS во время рендеринга страниц Fresh.
Использование стилей в компонентах

Компоненты можно стилизовать с помощью функции tw:

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

export default function Button() {
  return (
    <button class={tw`bg-primary text-white px-4 py-2 rounded hover:bg-secondary`}>
      Нажми меня
    </button>
  );
}

Особенности:

  • Все классы компилируются в CSS во время сборки.
  • Поддерживаются динамические классы через шаблонные строки.
  • Минимизация и дедупликация стилей происходит автоматически.

Реактивные islands с Twind

Компоненты islands используют Twind аналогично:

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

export default function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div class={tw`flex flex-col items-center`}>
      <span class={tw`text-2xl font-bold`}>{count}</span>
      <button
        class={tw`mt-2 px-4 py-2 bg-primary text-white rounded hover:bg-secondary`}
        onCl ick={() => setCount(count + 1)}
      >
        Увеличить
      </button>
    </div>
  );
}

Ключевые моменты работы с islands:

  • Islands рендерятся на сервере и загружаются на клиент при необходимости.
  • Twind позволяет применять стили сразу на сервере, что исключает FOUC (Flash of Unstyled Content).
  • Стили для islands генерируются отдельно, но объединяются в общий CSS.

Расширенные возможности плагина

  1. Dark Mode:
setup({
  theme: {},
  darkMode: "class",
});
  1. Произвольные плагины Tailwind:
import { defineConfig } from "twind";
import aspectRatio from "@twind/aspect-ratio";

defineConfig({
  plugins: { aspectRatio },
});
  1. Интеграция с PostCSS или другими инструментами не требуется — Twind генерирует CSS полностью на лету.

Производительность и оптимизация

  • Fresh и Twind обеспечивают минимальный JS-бандл, так как CSS генерируется по факту использования классов.
  • Серверный рендеринг снижает время до первого отображения (TTFB) и улучшает SEO.
  • Динамическая генерация стилей позволяет избегать лишнего CSS, что уменьшает объем передаваемых данных.

Практические советы

  • Использовать islands только для интерактивных компонентов, остальные части страницы рендерить статически.
  • Выносить общие утилитарные стили в конфигурацию Twind.
  • Следить за уникальностью классов при динамическом создании стилей через шаблонные строки.

Fresh с плагином Twind обеспечивает легковесное, реактивное и высокопроизводительное решение для построения современных веб-приложений с минимальной зависимостью от сборщиков и сложных инструментов.