Package management

Фреймворк Fresh основан на современном подходе к разработке на Deno, что накладывает специфические особенности на работу с зависимостями и пакетами. В отличие от традиционных Node.js-проектов, где управление пакетами осуществляется через npm или yarn, в Fresh используется встроенный механизм импорта модулей напрямую из URL или через локальные модули, а также поддержка Deno.land/x репозиториев.

Структура зависимостей

В проектах Fresh зависимости чаще всего хранятся в двух основных формах:

  1. Удалённые модули по URL Пример импорта:

    import { serve } from "https://deno.land/std@0.203.0/http/server.ts";
    import { h } from "https://esm.sh/preact@10.13.1";

    В этом случае Deno автоматически кеширует модули локально после первого запроса, что обеспечивает быстрый повторный запуск и стабильность версий.

  2. Локальные модули Для модулей, которые часто изменяются, рекомендуется хранить их в проекте в папке components, utils или routes.

    import { Header } from "./components/Header.tsx";
    import { fetchUser } from "./utils/api.ts";

Файл import_map.json

Для упрощения работы с URL-импортами используется Import Map, который позволяет определять алиасы и фиксировать версии пакетов.

Пример import_map.json:

{
  "imports": {
    "preact/": "https://esm.sh/preact@10.13.1/",
    "preact/hooks": "https://esm.sh/preact@10.13.1/hooks"
  }
}

Импорт в коде становится более читаемым:

import { h } from "preact";
import { useState } from "preact/hooks";

Запуск приложения с поддержкой import_map.json:

deno run --import-map=import_map.json -A dev.ts

Установка сторонних пакетов

Fresh поддерживает подключение популярных библиотек через ESM CDN, например esm.sh, skypack.dev или jspm.io. Это позволяет подключать пакеты, которые традиционно использовались в Node.js:

import _ from "https://esm.sh/lodash@4.17.21";

Важно контролировать версии, так как любой URL может ссылаться на разные версии при обновлении без явного указания. Для этого в URL указывается фиксированная версия.

Управление зависимостями проекта

В Deno и Fresh нет привычного package.json, вместо него:

  • deno.json или deno.jsonc — основной конфигурационный файл проекта.

  • В deno.json можно указать:

    • скрипты для запуска (tasks)
    • настройки форматирования
    • пути к import map
    • флаги безопасности (permissions)

Пример конфигурации:

{
  "tasks": {
    "start": "deno run --allow-net --import-map=import_map.json dev.ts",
    "lint": "deno lint"
  },
  "importMap": "./import_map.json",
  "lint": {
    "rules": {
      "tags": ["recommended"]
    }
  }
}

Кэширование и обновление модулей

Deno автоматически кэширует все скачанные модули в локальном хранилище. Управление кэшем осуществляется через:

  • deno cache mod.ts — предварительная загрузка модулей.
  • deno info mod.ts — информация о кэше и зависимостях.
  • deno cache --reload mod.ts — принудительное обновление модулей.

Этот подход обеспечивает детерминированность сборки: проект всегда использует закешированные версии, если явно не указано обновление.

Работа с локальными пакетами и монорепозиториями

Для крупных проектов часто используют структуру монорепозитория, где Fresh является частью. В этом случае:

  • Общие модули хранятся в packages/
  • Каждая папка имеет отдельные компоненты, utils, страницы
  • Импорты делаются через относительные пути или через import_map.json

Пример структуры:

project/
├─ deno.json
├─ import_map.json
├─ apps/
│  └─ web/
│     ├─ routes/
│     └─ components/
└─ packages/
   └─ ui/
      └─ Button.tsx

Импорт из монопакета через import map:

{
  "imports": {
    "ui/": "./packages/ui/"
  }
}
import { Button } from "ui/Button.tsx";

Безопасность зависимостей

Fresh наследует модель безопасности Deno: каждый модуль, который запрашивает доступ к сети, файловой системе или окружению, должен быть явно разрешён через флаги --allow-net, --allow-read и другие. Это позволяет избежать незаметного выполнения кода сторонних пакетов.

Автоматизация и скрипты

Для управления пакетами часто используют встроенные tasks в deno.json вместо сторонних npm-скриптов:

{
  "tasks": {
    "dev": "deno run --allow-net dev.ts",
    "build": "deno task build"
  }
}

Таким образом, управление пакетами в Fresh совмещает преимущества ESM, прямого URL-импорта и строгой безопасности, что упрощает разработку масштабируемых приложений без громоздкой экосистемы Node.js.