Fresh — серверный фреймворк для Deno, построенный вокруг идеи island architecture, строгой модульности и нулевой сборки на сервере. Интеграция существующих JavaScript-библиотек в такой контекст требует понимания нескольких фундаментальных особенностей: среды выполнения Deno, модели загрузки модулей, работы с клиентским JavaScript и ограничений серверного рендеринга.
Ключевая особенность заключается в том, что Fresh не использует bundler на сервере. Любая библиотека подключается как ES-модуль напрямую, а значит, она должна быть либо изначально совместима с ESM, либо адаптируема к такому формату.
Современные версии Deno поддерживают импорт npm-пакетов без промежуточной сборки. Fresh полностью совместим с этим механизмом.
Пример импорта библиотеки из npm:
import lodash from "npm:lodash";
Особенности такого подхода:
npm:node_modules, зависимости хранятся
централизованноПри работе с Fresh важно учитывать, что:
Fresh строго разделяет серверный и клиентский код. Любая библиотека, требующая браузерного окружения (DOM, window, document), подключается исключительно внутри island-компонентов.
Пример использования клиентской библиотеки:
// islands/Chart.tsx
import { useEffect } from "preact/hooks";
import Chart from "npm:chart.js/auto";
export default function ChartIsland() {
useEffect(() => {
const ctx = document.getElementById("chart") as HTMLCanvasElement;
new Chart(ctx, {
type: "bar",
data: { /* ... */ },
});
}, []);
return <canvas id="chart"></canvas>;
}
Ключевые моменты:
useEffectНекоторые библиотеки доступны только в формате UMD или CommonJS. В таких случаях возможны несколько стратегий.
Использование CDN с ESM-обёрткой
Сервисы вроде esm.sh, skypack.dev или jspm.io автоматически преобразуют пакеты в ESM:
import dayjs from "https://esm.sh/dayjs";
Преимущества:
Недостаток — зависимость от внешнего сервиса.
Для библиотек, которые ожидают глобальное наличие (например, старые
визуализационные или аналитические инструменты), используется
подключение через <script>.
В Fresh это делается на уровне layout или страницы:
export default function Page() {
return (
<>
<script src="https://cdn.example.com/library.js"></script>
<div id="app"></div>
</>
);
}
При таком подходе:
Использование этого метода оправдано только для legacy-решений.
Fresh позволяет подключать серверные библиотеки напрямую в обработчики маршрутов и middleware. Здесь ограничения минимальны, так как код выполняется в Deno без браузерных зависимостей.
Пример использования библиотеки для работы с JWT:
import { create, verify } from "npm:jsonwebtoken";
const token = create({ alg: "HS256", typ: "JWT" }, payload, secret);
Важно учитывать:
fs, net,
child_process) недоступны без полифилловFresh не навязывает систему стилей. CSS-библиотеки интегрируются стандартными способами.
Через CDN
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css"
/>
Через локальные файлы
<link rel="stylesheet" href="/styles/main.css" />
Для компонентных UI-библиотек на Preact:
Fresh использует TypeScript по умолчанию, поэтому корректная типизация библиотек играет важную роль.
Возможные ситуации:
@types/* через npmd.ts файлыПример объявления типа:
declare module "legacy-lib" {
export function init(config: unknown): void;
}
Интеграция библиотек должна учитывать философию Fresh — минимальный JavaScript на клиенте.
Практики оптимизации:
Fresh автоматически отправляет клиенту только код, необходимый для конкретных island, что делает избыточные зависимости особенно заметными.
Часто возникающие сложности при интеграции:
window на уровне модуляrequireprocess.envРешения включают:
useEffectПри работе с Fresh предпочтение отдаётся библиотекам, которые:
Такой подход позволяет сохранить предсказуемость архитектуры, минимальный размер клиентского кода и высокую производительность без усложнения инфраструктуры.