Spec-Zone.ru › Deno 2

Рабочие области и монорепозитории

Deno поддерживает рабочие области, также известные как «монорепозитории», которые позволяют одновременно управлять несколькими связанными и взаимозависимыми пакетами.

«Рабочая область» — это набор папок, содержащих файлы конфигурации deno.json или package.json. Корневой файл deno.json определяет рабочую область:

deno.json
{
  "workspace": ["./add", "./subtract"]
}

В этой конфигурации рабочей области указаны участники add и subtract — каталоги, в которых ожидается наличие файлов deno.json(c) и/или package.json.

Каталог каждого участника рабочей области может содержать:

  • Только deno.json (пакет, ориентированный в первую очередь на Deno)
  • И deno.json, и package.json (гибридный пакет — полезно при миграции или когда вам нужны метаданные Node наряду с конфигурацией Deno)
  • Только package.json (пакет, ориентированный в первую очередь на Node, который при этом участвует в рабочей области Deno)

Если участник содержит только package.json, его всё равно можно импортировать из любой точки рабочей области с помощью поля name, указанного в этом package.json (например, import { something } from "@scope/my-node-only-pkg";). Deno разрешит этот неуточнённый спецификатор, если каталог указан в конфигурации корневой рабочей области. Это позволяет постепенно переходить на инструменты Deno, не добавляя заранее deno.json в каждый существующий пакет Node.

Терминология

Для обозначения единой рабочей области с несколькими участниками Deno использует workspace, а не workspaces из npm.

Пример

Рассмотрим подробнее пример рабочей области deno.json и посмотрим, как она работает. Иерархия файлов выглядит так:

›_
/
├── deno.json
├── main.ts
├── add/
│     ├── deno.json
│     └── mod.ts
└── subtract/
      ├── deno.json
      └── mod.ts

В рабочей области два участника (add и subtract), каждый со своими файлами mod.ts. Также в корне находятся deno.json и main.ts.

Файл конфигурации deno.json верхнего уровня определяет рабочую область и карту импортов верхнего уровня, применяемую ко всем участникам:

deno.json
{
  "workspace": ["./add", "./subtract"],
  "imports": {
    "chalk": "npm:chalk@5"
  }
}

Корневой файл main.ts использует неуточнённый спецификатор chalk из карты импортов и импортирует функции add и subtract из участников рабочей области. Обратите внимание, что для импорта используются @scope/add и @scope/subtract, хотя это не настоящие URL и их нет в карте импортов. Как они разрешаются?

main.ts
import chalk from "chalk";
import { add } from "@scope/add";
import { subtract } from "@scope/subtract";

console.log("1 + 2 =", chalk.green(add(1, 2)));
console.log("2 - 4 =", chalk.red(subtract(2, 4)));

В подкаталоге add/ мы определяем deno.json с полем "name", необходимым для ссылки на участника рабочей области. Файл deno.json также содержит примеры конфигурации, например отключение точек с запятой при использовании deno fmt.

add/deno.json
{
  "name": "@scope/add",
  "version": "0.1.0",
  "exports": "./mod.ts",
  "fmt": {
    "semiColons": false
  }
}
add/mod.ts
export function add(a: number, b: number): number {
  return a + b;
}

Подкаталог subtract/ устроен аналогично, но в нём нет такой же конфигурации deno fmt.

subtract/deno.json
{
  "name": "@scope/subtract",
  "version": "0.3.0",
  "exports": "./mod.ts"
}
subtract/mod.ts
import { add } from "@scope/add";

export function subtract(a: number, b: number): number {
  return add(a, b * -1);
}

Запустим проект:

›_
> deno run main.ts
1 + 2 = 3
2 - 4 = -2

Здесь есть на что обратить внимание: пример демонстрирует несколько возможностей рабочих областей Deno:

  1. Этот монорепозиторий состоит из двух пакетов, расположенных в каталогах ./add и ./subtract.

  2. Параметры name и version в файлах deno.json участников позволяют ссылаться на них во всей рабочей области с помощью «неуточнённых спецификаторов». В данном случае пакеты называются @scope/add и @scope/subtract, где scope — выбранное вами имя «области». Благодаря этим параметрам в инструкциях импорта не нужно указывать длинные относительные пути к файлам.

  3. Пакет npm:chalk@5 — общая зависимость для всей рабочей области. Участники рабочей области «наследуют» imports корня рабочей области, что позволяет легко использовать одну версию зависимости во всей кодовой базе.

  4. В подкаталоге add в файле deno.json указано, что deno fmt не следует добавлять точки с запятой при форматировании кода. Это значительно упрощает переход для существующих проектов, избавляя от необходимости сразу изменять десятки или сотни файлов.


Рабочие области Deno гибкие и совместимы с пакетами Node. Чтобы упростить миграцию существующих проектов Node.js, в одной рабочей области можно использовать как пакеты, ориентированные в первую очередь на Deno, так и пакеты, ориентированные в первую очередь на Node.

Шаблоны путей рабочей области

Deno поддерживает сопоставление шаблонов для каталогов участников рабочей области. Это упрощает управление рабочими областями с большим количеством участников или определённой структурой каталогов. С помощью шаблонов с подстановочными знаками можно включить сразу несколько каталогов:

deno.json
{
  "workspace": [
    "some-dir/*",
    "other-dir/*/*"
  ]
}
Информация

Поддержка шаблонов появилась в Deno 2.1.

Синтаксис сопоставления шаблонов подчиняется определённым правилам, связанным с глубиной вложенности каталогов:

Шаблон some-path/* соответствует файлам и каталогам непосредственно внутри some-path (только первый уровень вложенности). Например, при использовании packages/* в него входят packages/foo и packages/bar, но не packages/foo/subpackage.

Шаблон some-path/*/* соответствует файлам и каталогам, расположенным в подкаталогах some-path (второй уровень вложенности). Он не соответствует элементам непосредственно внутри some-path. Например, при использовании examples/*/* в него входят examples/basic/demo и examples/advanced/sample, но не examples/basic.

Каждый сегмент /* в шаблоне соответствует определённому уровню вложенности папки относительно базового пути. Благодаря этому можно точно указывать участников рабочей области на разных уровнях структуры каталогов.

Рекурсивное сопоставление

Используйте **, чтобы сопоставлять каталоги на любой глубине ниже базового пути, а не ограничиваться одним уровнем. Например, шаблон packages/** соответствует packages/foo, packages/foo/subpackage и любым более глубоким каталогам, содержащим файл конфигурации:

deno.json
{
  "workspace": ["packages/**"]
}

Исключение участников

Добавьте перед шаблоном !, чтобы исключить каталоги, которые в противном случае были бы включены предыдущим шаблоном. Это удобно, если шаблон с подстановочным знаком захватывает каталог, который не должен быть участником рабочей области. После ! можно указывать как буквальные пути, так и шаблоны:

deno.json
{
  "workspace": [
    "packages/*",
    "!packages/internal",
    "!packages/*/fixtures"
  ]
}

Здесь packages/* включает все каталоги внутри packages, а затем два исключения исключают packages/internal и любой каталог fixtures на один уровень ниже.

Как Deno разрешает зависимости рабочей области

При запуске проекта в рабочей области, который импортирует модуль из другого участника рабочей области, Deno выполняет следующие действия для разрешения зависимостей:

  1. Deno начинает с каталога запускаемого проекта (например, проекта A)
  2. В родительском каталоге ищет корневой файл deno.json
  3. Если файл найден, проверяет наличие в нём свойства workspace
  4. Для каждой инструкции импорта в проекте A Deno проверяет, соответствует ли импорт имени пакета, определённому в файле deno.json какого-либо участника рабочей области
  5. Если совпадающее имя пакета найдено, Deno проверяет, указан ли содержащий его каталог в конфигурации корневой рабочей области
  6. Затем импорт разрешается в нужный файл с помощью поля exports в файле deno.json участника рабочей области

Например, при такой структуре:

›_
/
├── deno.json         # workspace: ["./project-a", "./project-b"]
├── project-a/
│   ├── deno.json     # name: "@scope/project-a"
│   └── mod.ts        # imports from "@scope/project-b"
└── project-b/
    ├── deno.json     # name: "@scope/project-b"
    └── mod.ts

Когда project-a/mod.ts импортирует модуль из "@scope/project-b", Deno:

  1. Находит инструкцию импорта
  2. Проверяет файл deno.json в родительском каталоге
  3. Находит project-b в массиве рабочей области
  4. Проверяет, существует ли project-b/deno.json и совпадает ли имя пакета
  5. Разрешает импорт с помощью экспорта из project-b

Важное замечание о создании контейнеров

При создании контейнера для участника рабочей области, зависящего от других участников, необходимо включить:

  1. Корневой файл deno.json
  2. Все зависимые пакеты рабочей области
  3. Ту же структуру каталогов, что и в среде разработки

Например, если вы создаёте Docker-образ для project-a из примера выше, в Dockerfile нужно:

COPY deno.json /app/deno.json
COPY project-a/ /app/project-a/
COPY project-b/ /app/project-b/

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

Несколько точек входа пакета

Свойство exports описывает точки входа и указывает, какие модули могут импортировать пользователи вашего пакета.

Пока что у нашего пакета только одна точка входа. Для простых пакетов этого достаточно, но часто бывает полезно иметь несколько точек входа, объединяющих связанные компоненты пакета. Для этого вместо string в exports можно передать object:

my-package/deno.json
{
  "name": "@scope/my-package",
  "version": "0.3.0",
  "exports": {
    ".": "./mod.ts",
    "./foo": "./foo.ts",
    "./other": "./dir/other.ts"
  }
}

Точка входа "." используется по умолчанию при импорте @scope/my-package. Таким образом, в примере deno.json выше доступны следующие точки входа:

  • @scope/my-package
  • @scope/my-package/foo
  • @scope/my-package/other

Публикация пакетов рабочей области в реестрах

Рабочие области упрощают публикацию пакетов в таких реестрах, как JSR или NPM. Вы можете публиковать отдельных участников рабочей области, сохраняя их взаимосвязь при разработке в монорепозитории.

Публикация в JSR

Чтобы опубликовать пакет рабочей области в JSR, выполните следующие действия:

  1. Убедитесь, что в файле deno.json каждого пакета указаны необходимые метаданные:
my-package/deno.json
{
  "name": "@scope/my-package",
  "version": "1.0.0",
  "exports": "./mod.ts",
  "publish": {
    "exclude": ["tests/", "*.test.ts", "examples/"]
  }
}
  1. Перейдите в каталог нужного пакета и опубликуйте его:
›_
cd my-package
deno publish

Исключение участника рабочей области из публикации

В рабочих областях часто есть участники, которые не предназначены для публикации: например, внутренние вспомогательные пакеты, примеры или пакеты, предназначенные только для размещения общих tasks. По умолчанию deno publish попытается опубликовать каждого участника рабочей области, у которого есть name и exports, и выдаст ошибку, если у кого-либо из них отсутствует version.

Чтобы исключить участника из deno publish, задайте "publish": false в файле deno.json этого участника:

internal-helpers/deno.json
{
  "name": "@scope/internal-helpers",
  "tasks": {
    "build": "deno run -A scripts/build.ts"
  },
  "publish": false
}

При этом участник по-прежнему входит в рабочую область. Его tasks запускаются, его imports разрешаются, и от него могут зависеть другие участники. Однако deno publish полностью пропускает его и не выдаёт ошибку из-за отсутствующего version.

Это относится только к участникам deno.json. Участники рабочей области, определённые только через package.json, являются пакетами npm и никогда не рассматриваются для deno publish (которая предназначена для JSR), поэтому исключать их не нужно. Deno не считывает поле "private": true из package.json.

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

При публикации пакетов из рабочей области с взаимозависимостями придерживайтесь единой схемы версионирования для связанных пакетов. Сначала публикуйте пакеты, от которых зависят другие, а затем пакеты, которые от них зависят. После публикации убедитесь, что опубликованные пакеты работают как ожидается:

›_
# Test a published package
deno add jsr:@scope/my-published-package
deno test integration-test.ts

При публикации пакетов, зависящих от других участников рабочей области, Deno автоматически заменяет ссылки на участников рабочей области в публикуемом коде корректными ссылками на реестр.

Переход с рабочих областей npm

Рабочие области Deno позволяют использовать пакет, ориентированный в первую очередь на Deno, в существующем пакете npm. В этом примере мы объединяем библиотеку Deno @deno/hi с библиотекой Node.js @deno/log, которую разработали пару лет назад.

Добавим в корень файл конфигурации deno.json:

deno.json
{
  "workspace": {
    "members": ["hi"]
  }
}

А рядом оставим существующую рабочую область package.json:

package.json
{
  "workspaces": ["log"]
}

В рабочей области уже есть пакет npm log:

log/package.json
{
  "name": "@deno/log",
  "version": "0.5.0",
  "type": "module",
  "main": "index.js"
}
log/index.js
export function log(output) {
  console.log(output);
}

Создадим пакет Deno, ориентированный в первую очередь на Deno, @deno/hi, который импортирует @deno/log:

hi/deno.json
{
  "name": "@deno/hi",
  "version": "0.2.0",
  "exports": "./mod.ts",
  "imports": {
    "log": "npm:@deno/log@^0.5"
  }
}
hi/mod.ts
import { log } from "log";

export function sayHiTo(name: string) {
  log(`Hi, ${name}!`);
}

Теперь можно написать файл main.ts, который импортирует и вызывает hi:

main.ts
import { sayHiTo } from "@deno/hi";

sayHiTo("friend");
›_
$ deno run main.ts
Hi, friend!

В существующем пакете Node.js можно использовать одновременно deno.json и package.json. Кроме того, можно удалить корневой package.json и указать пакет npm в участниках рабочей области deno.json. Это позволяет постепенно перейти на Deno без большого объёма предварительной работы.

Например, можно добавить log/deno.json, чтобы настроить линтер и форматтер Deno:

{
  "fmt": {
    "semiColons": false
  },
  "lint": {
    "rules": {
      "exclude": ["no-unused-vars"]
    }
  }
}

При запуске deno fmt в рабочей области пакет log будет отформатирован без точек с запятой, а deno lint не будет выдавать предупреждение, если в одном из исходных файлов останется неиспользуемая переменная.

Настройка встроенных инструментов Deno

Некоторые параметры конфигурации имеют смысл только в корне рабочей области. Например, указать параметр nodeModulesDir в одном из участников нельзя, и Deno выдаст предупреждение, если параметр необходимо задать в корне рабочей области.

Ниже приведена полная таблица различных параметров deno.json, доступных в корне рабочей области и её участниках:

Параметр Рабочая область Пакет Примечания
compilerOptions ✅ ✅
importMap ✅ ❌ Несовместим с imports и scopes в одном файле конфигурации. Кроме того, нельзя использовать importMap в конфигурации рабочей области и imports в конфигурации пакета.
imports ✅ ✅ Несовместим с importMap в одном файле конфигурации.
scopes ✅ ❌ Несовместим с importMap в одном файле конфигурации.
exclude ✅ ✅
lint.include ✅ ✅
lint.exclude ✅ ✅
lint.files ⚠️ ❌ Устарело
lint.rules.tags ✅ ✅ Теги объединяются: теги пакета добавляются к списку рабочей области. Дубликаты игнорируются.
lint.rules.include ✅ ✅ Правила объединяются для каждого пакета, причём настройки пакета имеют приоритет над настройками рабочей области (включение в пакете сильнее исключения в рабочей области).
lint.rules.exclude ✅ ✅ Правила объединяются для каждого пакета, причём настройки пакета имеют приоритет над настройками рабочей области (включение в пакете сильнее исключения в рабочей области).
lint.report ✅ ❌ Одновременно может использоваться только один формат вывода, поэтому разные форматы для разных частей рабочей области не подойдут, если проверяются файлы из нескольких пакетов.
fmt.include ✅ ✅
fmt.exclude ✅ ✅
fmt.files ⚠️ ❌ Устарело
fmt.useTabs ✅ ✅ Настройка пакета имеет приоритет над настройкой рабочей области.
fmt.indentWidth ✅ ✅ Настройка пакета имеет приоритет над настройкой рабочей области.
fmt.singleQuote ✅ ✅ Настройка пакета имеет приоритет над настройкой рабочей области.
fmt.proseWrap ✅ ✅ Настройка пакета имеет приоритет над настройкой рабочей области.
fmt.semiColons ✅ ✅ Настройка пакета имеет приоритет над настройкой рабочей области.
fmt.options.* ⚠️ ❌ Устарело
minimumDependencyAge ✅ ❌ Поведение при разрешении зависимостей должно быть одинаковым во всей рабочей области.
nodeModulesDir ✅ ❌ Поведение при разрешении зависимостей должно быть одинаковым во всей рабочей области.
vendor ✅ ❌ Поведение при разрешении зависимостей должно быть одинаковым во всей рабочей области.
allowScripts ✅ ❌ Параметр необходимо задать в корне рабочей области, чтобы обеспечить единые правила безопасности для всех пакетов.
links ✅ ❌ Учитывается только в корне рабочей области.
tasks ✅ ✅ Задачи пакета имеют приоритет над задачами рабочей области. В качестве cwd используется cwd файла конфигурации, в котором определена задача.
test.include ✅ ✅
test.exclude ✅ ✅
test.files ⚠️ ❌ Устарело
publish ❌ ✅ Задайте значение false, чтобы исключить участника из deno publish. См. раздел «Исключение участника рабочей области из публикации».
publish.include ✅ ✅
publish.exclude ✅ ✅
bench.include ✅ ✅
bench.exclude ✅ ✅
bench.files ⚠️ ❌ Устарело
lock ✅ ❌ Для каждого обработчика зависимостей может существовать только один файл блокировки, а в рабочей области — только один обработчик зависимостей. Поэтому условное включение файла блокировки для каждого пакета не имеет смысла.
unstable ✅ ❌ Для простоты мы не разрешаем нестабильные флаги, поскольку многие компоненты CLI предполагают, что такие флаги неизменны и действуют глобально для всего процесса. Кроме того, они могут неожиданно взаимодействовать с флагами DENO_UNSTABLE_*.
name ❌ ✅
version ❌ ✅
exports ❌ ✅
workspace ✅ ❌ Вложенные рабочие области не поддерживаются.

Запуск команд во всех пакетах рабочей области

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

Проверка типов

У участников рабочей области могут быть разные наборы параметров компилятора. Они также наследуются от корневой конфигурации участниками и наоборот, подобно TSConfig extends. Например:

deno.json
{
  "workspace": ["./web"],
  "compilerOptions": {
    "checkJs": true
  }
}
web/deno.json
{
  "compilerOptions": {
    "lib": ["esnext", "dom"]
  }
}

Для файлов в подкаталоге web будут заданы следующие параметры:

{
  "compilerOptions": {
    "checkJs": true,
    "lib": ["esnext", "dom"]
  }
}

Каждый участник будет проверяться отдельно, независимо от остальных. Просто запустите deno check из корня рабочей области:

›_
deno check

Запуск тестов

Чтобы запустить тесты для всех участников рабочей области, выполните deno test из корня рабочей области:

›_
deno test

Тесты будут запущены во всех участниках рабочей области с учётом индивидуальных конфигураций тестирования.

Чтобы запустить тесты для определённого участника рабочей области, можно:

  1. Перейти в каталог этого участника и выполнить команду запуска тестов:
›_
cd my-directory
deno test
  1. Или указать путь от корня рабочей области:
›_
deno test my-directory/

Форматирование и линтинг

Как и тесты, команды форматирования и линтинга по умолчанию выполняются для всех участников рабочей области:

›_
deno fmt
deno lint

Каждый участник рабочей области использует собственные правила форматирования и линтинга, заданные в файле deno.json. Некоторые параметры наследуются из корневой конфигурации, как показано в таблице выше.

Использование задач рабочей области

Задачи можно определять как в корне рабочей области, так и в отдельных её участниках:

deno.json
{
  "workspace": ["./add", "./subtract"],
  "tasks": {
    "build": "echo 'Building all packages'",
    "test:all": "deno test"
  }
}
add/deno.json
{
  "name": "@scope/add",
  "version": "0.1.0",
  "exports": "./mod.ts",
  "tasks": {
    "build": "echo 'Building add package'",
    "test": "deno test"
  }
}

Чтобы запустить задачу, определённую в конкретном пакете:

›_
deno task --cwd=add build

Совместное использование зависимостей и управление ими

Участники рабочей области могут совместно использовать зависимости, зависеть друг от друга и разрешать конфликты версий отдельно для каждого участника. О том, как закрепить одну версию зависимости для всей рабочей области, см. ниже в разделе catalog:.

Рабочие области предоставляют широкие возможности для совместного использования зависимостей и управления ими в разных проектах:

Совместное использование зависимостей для разработки

Общие зависимости для разработки, например библиотеки тестирования, можно определить в корне рабочей области:

deno.json
{
  "workspace": ["./add", "./subtract"],
  "imports": {
    "@std/testing/": "jsr:@std/testing@^0.218.0/",
    "chai": "npm:chai@^4.3.7"
  }
}

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

Управление конфликтами версий

При разрешении зависимостей участники рабочей области могут переопределять зависимости, заданные в корне. Если в корне и участнике указаны разные версии одной зависимости, при разрешении зависимостей в каталоге этого участника будет использоваться версия участника. Благодаря этому отдельные пакеты могут при необходимости использовать конкретные версии зависимостей.

Однако зависимости, заданные для конкретного участника, действуют только в его каталоге. За пределами каталогов участников, а также при работе с файлами в корне рабочей области, для разрешения зависимостей (в том числе зависимостей JSR и HTTPS) используется карта импортов корня рабочей области.

Взаимозависимые участники рабочей области

Как показано в предыдущем примере с модулями add и subtract, участники рабочей области могут зависеть друг от друга. Это позволяет чётко разделять обязанности и при этом совместно разрабатывать и тестировать взаимозависимые модули.

Модуль subtract импортирует функциональность из модуля add, демонстрируя, как участники рабочей области могут использовать возможности друг друга:

subtract/mod.ts
import { add } from "@scope/add";

export function subtract(a: number, b: number): number {
  return add(a, b * -1);
}

Такой подход позволяет:

  1. Разбивать сложные проекты на управляемые пакеты с узкой специализацией
  2. Совместно использовать код между пакетами без публикации в реестре
  3. Совместно тестировать и разрабатывать взаимозависимые модули
  4. Постепенно переводить монолитные кодовые базы на модульную архитектуру

Использование протокола workspace в package.json

Deno поддерживает спецификаторы протокола workspace в файлах package.json. Они полезны, если пакеты npm зависят от других пакетов в рабочей области:

package.json
{
  "name": "my-npm-package",
  "dependencies": {
    "another-workspace-package": "workspace:*"
  }
}

Поддерживаются следующие спецификаторы протокола workspace:

  • workspace:* — использовать последнюю версию, доступную в рабочей области
  • workspace:~ — использовать версию из рабочей области только с изменениями уровня исправлений
  • workspace:^ — использовать версию из рабочей области с изменениями, совместимыми с semver

Централизованное управление версиями зависимостей с помощью catalog:

Если несколько участников рабочей области зависят от одного пакета npm, синхронизация версий обычно требует редактировать package.json каждого участника при каждом обновлении версии. Протокол catalog:, появившийся в Deno 2.8 и совместимый с аналогичной функцией в pnpm, Bun и Yarn, позволяет задать одно требование к версии в корне рабочей области, а каждому участнику ссылаться на него по имени.

Ссылка catalog: может указываться в зависимостях package.json участника или, начиная с Deno 2.9, в imports файла deno.json участника. Сам каталог определяется либо в deno.json, либо в package.json в корне рабочей области.

Каталоги предназначены только для npm

Каталоги управляют только зависимостями npm. Запись каталога — это имя пакета без спецификатора, сопоставленное с требованием к версии, а ссылка catalog: всегда разрешается в спецификатор npm: — указать в записи каталога пакет jsr: нельзя. Вместо этого управляйте зависимостями jsr: непосредственно через imports. Поскольку записи каталога рассматриваются как пакеты npm, deno update и deno outdated разрешают их через реестр npm.

Определите каталог в корневом файле deno.json:

deno.json
{
  "workspace": ["./packages/a", "./packages/b"],
  "catalog": {
    "react": "^18.3.0",
    "react-dom": "^18.3.0",
    "chalk": "^5.3.0"
  }
}

Участник ссылается на запись с помощью catalog: (каталога по умолчанию):

packages/a/package.json
{
  "dependencies": {
    "react": "catalog:",
    "react-dom": "catalog:"
  }
}

Чтобы обновить React до новой версии во всех пакетах, достаточно изменить каталог один раз.

Именованные каталоги

Используйте поле во множественном числе catalogs, если разным участникам нужны разные версии одного пакета — например, при переходе между основными версиями:

deno.json
{
  "workspace": ["./packages/a", "./packages/b"],
  "catalogs": {
    "react18": {
      "react": "^18.3.0",
      "react-dom": "^18.3.0"
    },
    "react19": {
      "react": "^19.0.0",
      "react-dom": "^19.0.0"
    }
  }
}

Участники выбирают каталог по имени:

packages/a/package.json
{
  "dependencies": {
    "react": "catalog:react18",
    "react-dom": "catalog:react18"
  }
}
packages/b/package.json
{
  "dependencies": {
    "react": "catalog:react19",
    "react-dom": "catalog:react19"
  }
}

catalog: (без имени) и catalog:default эквивалентны и разрешаются в единственное поле catalog.

Каталоги в package.json

Каталоги также могут находиться в корневом package.json, что позволяет хранить конфигурацию проекта в одном месте, если проект ещё не перешёл на deno.json:

package.json
{
  "catalog": {
    "react": "^19.0.0"
  },
  "catalogs": {
    "testing": {
      "vitest": "^2.0.0"
    }
  }
}

Если и deno.json, и package.json определяют каталоги в корне рабочей области, package.json полностью имеет приоритет — эти настройки не объединяются.

Ограничения

  • Каталоги доступны только для npm. Каждая запись разрешается в пакет npm:, поэтому зависимости jsr: (и другие зависимости, не относящиеся к npm) нельзя управлять через каталог.
  • Каталоги можно определять только в корне. Определение catalog или catalogs внутри участника рабочей области приводит к появлению диагностического сообщения.
  • Участники должны ссылаться на имя существующего каталога. Отсутствующая запись приводит к ошибке разрешения зависимостей при установке или запуске.

Совместимость рабочих областей npm и pnpm

Deno без проблем работает со стандартными рабочими областями npm, определёнными в package.json:

package.json
{
  "workspaces": ["packages/*"]
}

Для пользователей pnpm Deno поддерживает типичные конфигурации рабочих областей pnpm. Однако, если вы используете файл pnpm-workspace.yaml, необходимо перейти на конфигурацию рабочей области deno.json:

pnpm-workspace.yaml (будет заменён)
packages:
  - "packages/*"

Его следует преобразовать в:

deno.json
{
  "workspace": ["packages/*"]
}

Это обеспечивает плавную интеграцию Deno с экосистемами npm/pnpm при миграции или в гибридных проектах.

Дополнительную информацию о настройке проекта см. в руководстве Настройка с помощью deno.json.

Последнее обновление: 29 июня 2026 г.

© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/runtime/fundamentals/workspaces

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API