Fresh — это современный подход к построению веб-приложений, где страницы рендерятся на сервере, а интерактивность добавляется только на отдельных участках интерфейса, называемых островами интерактивности. Этот подход минимизирует объем клиентского JavaScript и ускоряет загрузку страниц, сочетая преимущества серверного рендеринга и динамического поведения на фронтенде.
Остров интерактивности — это компонент, который:
Преимущества такого подхода:
Серверный рендеринг (SSR) Все компоненты страницы изначально формируются на сервере. Это обеспечивает быстрый первый рендер и хорошую SEO-оптимизацию.
Гидратация острова Когда браузер загружает страницу, скрипт, относящийся к конкретному острову, выполняется и превращает статический HTML в интерактивный компонент.
Локализация интерактивности Только те участки страницы, которые действительно требуют динамического поведения, получают скрипты и события. Остальная часть страницы остается легкой и статичной.
Для создания островов интерактивности используются фреймворки, поддерживающие SSR, например Deno Fresh, Astro, Solid или Next.js с подходом “islands architecture”. Общая схема:
// server.js
import { render } from 'fresh';
import Counter from './components/Counter.js';
const html = render(<Counter initialCount={0} />);
// Counter.js
export default function Counter({ initialCount }) {
let count = initialCount;
function increment() {
count += 1;
updateView();
}
function updateView() {
document.getElementById('count').textContent = count;
}
return `
<div>
<span id="count">${count}</span>
<button oncl ick="increment()">+1</button>
</div>
`;
}
В примере компонент Counter рендерится на сервере, а интерактивность кнопки реализована через локальный скрипт, загружаемый только для этого острова.
On-load Скрипт выполняется после полной загрузки страницы.
On-visible Скрипт загружается, когда остров становится видимым на экране (Intersection Observer).
On-interaction Скрипт загружается только при взаимодействии пользователя, например при клике или наведении.
Состояние каждого острова должно быть локальным, чтобы избежать глобальных зависимостей:
function ToggleButton() {
let isActive = false;
function toggle() {
isActive = !isActive;
document.getElementById('toggle').textContent = isActive ? 'Вкл' : 'Выкл';
}
return `
<button id="toggle" oncl ick="toggle()">Выкл</button>
`;
}
Такая структура обеспечивает предсказуемое поведение и легкую отладку.
client:load, client:visible или
client:idle.