Spec-Zone.ru › Deno 2

Совместимость Node и npm

Большая часть кода Node.js работает в Deno без изменений. Вот стандартный HTTP-сервер Node, запущенный с помощью deno вместо node:

main.mjs
import { createServer } from "node:http";

const server = createServer((req, res) => {
  res.end("Hello from Node-style code in Deno\n");
});

server.listen(3000, () => {
  console.log("Listening on http://localhost:3000/");
});
›_
$ deno run --allow-net main.mjs
Listening on http://localhost:3000/

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

Краткий обзор совместимости

Область Статус Подробнее
node: встроенные модули Поддерживаются; реализованы почти все модули Использование встроенного модуля Node
Пакеты npm Поддерживаются через спецификаторы npm: или package.json Использование пакетов npm
Глобальные объекты Node (process, Buffer, __dirname) Поддерживаются; для некоторых нужен явный импорт Использование глобальных объектов Node
package.json (зависимости, скрипты, type) Поддерживается: зависимости, скрипты deno task, type Запуск существующего проекта Node
CommonJS (require(), .cjs) Поддерживается; в одном случае определение типа модуля работает иначе Поддержка CommonJS
node_modules структура каталогов Необязательно; три режима, изолированная или поднятая структура Управление node_modules
Нативные дополнения (Node-API) Поддерживаются при наличии локального каталога node_modules и --allow-ffi Использование пакетов с нативными дополнениями
.npmrc и реестры Поддерживаются: частные реестры, токены аутентификации, mTLS Частные реестры, Настройка .npmrc

По состоянию на Deno 2.8, в Deno проходит более 75% собственного набора тестов Node, который охватывает почти каждый модуль node:. Большинство пакетов npm на чистом JavaScript работают без изменений. Но есть и ограничения: некоторые API реализованы не полностью, пакетам с нативными дополнениями нужен локальный каталог node_modules, а некоторые инструменты предполагают точную структуру файлов на диске, используемую npm. В разделах ниже рассмотрен каждый из этих случаев.

Текущее состояние можно отслеживать на сайте node-test-viewer.deno.deno.net, а список поддерживаемых API Node.js доступен здесь.

Использование пакетов npm

Чтобы использовать пакет из npm, импортируйте его с префиксом npm: и запустите файл:

main.js
import * as emoji from "npm:node-emoji";

console.log(emoji.emojify(`:sauropod: :heart:  npm`));
›_
$ deno run main.js
🦕 ❤️ npm

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

npm:[@][/]

Вот несколько правил, о которых следует знать:

  • Пакеты npm работают в той же системе разрешений, что и остальной ваш код. Если пакет читает файлы или переменные среды, предоставьте разрешения -R или -E (либо ответьте на запросы разрешений).
  • Зависимости можно объявить в package.json или в карте imports файла deno.json вместо того, чтобы указывать спецификаторы npm: непосредственно в коде. См. раздел Запуск существующего проекта Node.
  • Если пакет завершается с ошибками о недостающих файлах в node_modules, значит, ему нужен локальный каталог node_modules. См. раздел Управление node_modules.

Примеры использования популярных библиотек приведены в разделе руководств.

Использование встроенного модуля Node

Deno предоставляет встроенные API Node через слой совместимости. Импортируйте их с префиксом node::

main.mjs
import * as os from "node:os";
console.log(os.cpus());

Запустите программу с помощью deno run main.mjs — результат будет таким же, как при запуске программы в Node.js. Если обновить все импорты в приложении, указав спецификаторы node:, код, использующий встроенные модули Node, должен работать так же, как в Node.js.

Встроенный модуль node:module включает API registerHooks(), с помощью которого можно настраивать разрешение и загрузку модулей внутри программы.

Можно использовать и короткие импорты без префикса. Начиная с Deno 2.9, спецификатор, соответствующий встроенному модулю Node, указывает на него и без префикса, поэтому import * as os from "os" работает без префикса и флага. До версии 2.9 короткая форма вызывала ошибку, если не включить ее нестабильным флагом. Тем не менее предпочтительна явная форма node:: она однозначна, именно ее вставляют быстрые исправления Deno LSP, и она также работает в Node.js. Запись deno.json imports или зависимость package.json с тем же именем по-прежнему имеет приоритет над встроенным модулем, а пакет node_modules больше не перекрывает его, как и в Node.js.

Ознакомиться со встроенными API Node

Использование глобальных объектов Node, например process и Buffer

Node.js определяет ряд глобальных объектов, доступных всем программам. Ниже показано, как наиболее распространенные из них представлены в Deno:

Глобальный объект Node В Deno Что делать
process Доступен везде Используйте как есть или импортируйте из node:process
Buffer Не является глобальным объектом в вашем коде Импортируйте из node:buffer
__filename Не определен Используйте import.meta.filename
__dirname Не определен Используйте import.meta.dirname
require() Доступен в файлах CommonJS См. раздел Поддержка CommonJS
setTimeout / setInterval Доступны; семантика Node начиная с Deno 2.8 Используйте как есть

Подробнее о каждом из них:

  • process — наиболее распространенный глобальный объект в пакетах npm, доступный всему коду. Чтобы предпочесть явный импорт node:process, включите правило линтера no-process-global (по умолчанию отключено начиная с Deno 2.8); после этого deno lint будет отмечать обращения к глобальному объекту:

    process.js
    console.log(process.versions.deno);
    
    $ deno run process.js
    2.8.3
    $ deno lint process.js
    error[no-process-global]: NodeJS process global is discouraged in Deno
     --> /process.js:1:13
      |
    1 | console.log(process.versions.deno);
      |             ^^^^^^^
      = hint: Add `import process from "node:process";`
    
      docs: https://docs.deno.com/lint/rules/no-process-global
    
    
    Found 1 problem (1 fixable via --fix)
    Checked 1 file
    

    Deno сообщает текущую версию, совместимую с Node: process.version — это v26.3.0, а process.versions.napi — 10 (версия Node-API 10), поэтому пакеты, проверяющие версию Node или Node-API, видят современную среду выполнения.

  • Buffer необходимо явно импортировать из модуля node:buffer:

    buffer.js
    import { Buffer } from "node:buffer";
    
    const buf = new Buffer(5, "0");
    

    Пользователи TypeScript, которым нужны специфичные для Node.js типы, например BufferEncoding, могут получить к ним доступ через пространство имен NodeJS при использовании @types/node:

    buffer-types.ts
    /// <reference types="npm:@types/node" />
    
    // Now you can use NodeJS namespace types
    function writeToBuffer(
      data: string,
      encoding: NodeJS.BufferEncoding,
    ): Buffer {
      return Buffer.from(data, encoding);
    }
    

    Вместо этого предпочтительно использовать Uint8Array или другие подклассы TypedArray.

  • setTimeout / setInterval: начиная с Deno 2.8, глобальные функции таймера возвращают объект Node.js Timeout, а не число, что соответствует семантике Node.js. У возвращаемого объекта есть такие методы, как .ref(), .unref(), .refresh() и .hasRef(). Он по-прежнему приводится к числу (через Symbol.toPrimitive), поэтому существующий код, который сохраняет идентификатор таймера как число или передает его в clearTimeout/clearInterval, продолжает работать без изменений.

    const t = setTimeout(() => {}, 1000);
    t.unref(); // don't keep the event loop alive for this timer
    clearTimeout(t);
    

Запуск существующего проекта Node

Deno понимает package.json, поэтому типичный проект Node запускается двумя командами: одной для установки, другой для запуска.

package.json
{
  "type": "module",
  "scripts": {
    "start": "node main.js"
  },
  "dependencies": {
    "chalk": "^5"
  }
}
main.js
import chalk from "chalk";
console.log(chalk.green("ready"));
›_
$ deno install
$ deno run -R -E main.js
ready

deno install читает package.json и создает каталог node_modules, поэтому короткие импорты, например "chalk", разрешаются так же, как в Node. Флаги -R и -E предоставляют доступ на чтение и к переменным среды, необходимые для разрешения node_modules (и определения цвета в chalk).

Что сохраняется из вашего package.json:

  • Зависимости, объявленные в нем, устанавливаются с помощью deno install и импортируются по короткому спецификатору.
  • Скрипты запускаются через deno task, например npm run: команда deno task start запускает скрипт start. Скрипты выполняются во встроенной кроссплатформенной оболочке Deno, а инструменты командной строки, установленные в node_modules/.bin (средства запуска тестов, сборщики, линтеры), разрешаются автоматически. При этом сами команды по-прежнему запускают указанные в них исполняемые файлы, поэтому скрипт, вызывающий node, запускает Node.
  • Поля, например "type", учитываются при разрешении модулей (см. раздел Поддержка CommonJS).
  • Ограничения engines проверяются: deno install выводит предупреждение для каждого package.json, если текущее время выполнения не удовлетворяет требованиям к версиям node или deno, — так же, как это делают npm и Yarn. Другие ключи среды выполнения (npm, yarn, pnpm) игнорируются.

Для проектов с package.json по умолчанию используется ручной режим node_modules, поэтому требуется явно выполнить шаг deno install. Альтернативы описаны в разделе Управление node_modules.

Если не работает: если запустить команду до установки, Deno сразу подскажет, как исправить проблему:

›_
$ deno run -R -E main.js
error: Could not resolve "chalk", but found it in a package.json. Deno expects the node_modules/ directory to be up to date. Did you forget to run `deno install`?
    at file:///my-app/main.js:1:19

Выполните deno install (или задайте "nodeModulesDir": "auto", чтобы пропустить явный шаг установки) и повторите попытку.

Полный список проверок, дополнительные улучшения инструментальной цепочки и шпаргалку по командам для перехода с Node на Deno см. в руководстве по переходу с Node.js на Deno.

Инструменты, запускающие node

Некоторые инструменты нативной сборки напрямую находят и запускают исполняемый файл node через операционную систему, обходя перехват node, который Deno обычно выполняет для скриптов и child_process. Показательный пример — Next.js 16: нативное дополнение Turbopack запускает пул рабочих процессов node для обработки CSS и загрузчиков шрифтов, поэтому в deno task dev эти этапы завершились бы ошибкой, если бы исполняемый файл node не был установлен.

Чтобы не устанавливать Node отдельно, Deno выступает вместо node. Если в PATH не найден настоящий node, Deno помещает исполняемый файл node в каталог кэша и добавляет этот каталог в начало PATH процессов, которые запускает. Затем инструмент, запускающий node, обращается к Deno, который преобразует аргументы Node и запускает его так, словно вы вызвали deno node ....

Это решение работает по принципу «как получится» и активируется только тогда, когда настоящий node отсутствует в PATH, поэтому существующая установка Node никогда не перекрывается. Чтобы отключить это поведение, задайте DENO_DISABLE_NODE_SHIM=1.

Запуск инструмента командной строки npm

Инструменты командной строки npm (пакеты с записями bin) можно запускать напрямую, как и с помощью npx:

›_
$ deno run -R -E npm:cowsay@1.5.0 "Hello there!"
 ______________
< Hello there! >
 --------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Формат спецификатора поддерживает подкаталог для выбора конкретного исполняемого файла, если пакет содержит несколько:

npm:[@][/]

Например, deno run -R -E npm:cowsay@1.5.0/cowthink запускает исполняемый файл cowthink из того же пакета. Инструменты для создания проектов работают так же; следующие две команды эквивалентны:

# npx allows remote execution of a package from npm or a URL
$ npx create-next-app@latest

# deno run allows remote execution of a package from various locations,
# and can be scoped to npm via the `npm:` specifier.
$ deno run -A npm:create-next-app@latest

Если не работает: инструменты, читающие файлы или переменные среды, остановятся на запросе разрешений (или завершатся с ошибкой в CI). Предоставьте необходимые инструменту разрешения либо -A для доверенных инструментов создания проектов, которым нужен широкий доступ.

Поддержка CommonJS

Deno по умолчанию поддерживает модули CommonJS. Ниже приведена минимальная рабочая настройка для файла .cjs с зависимостью npm:

deno.json
{
  "nodeModulesDir": "auto"
}
main.cjs
const express = require("express");
$ deno install npm:express
Dependencies:
+ npm:express 5.2.1

$ deno run -R -E main.cjs
[Function: createApplication] {
  application: {
    init: [Function: init],
    defaultConfiguration: [Function: defaultConfiguration],
    ...
  }
}

Для этого нужны два условия. Для разрешения модулей CommonJS зависимости должны быть установлены в локальный каталог node_modules; это обеспечивает "nodeModulesDir": "auto" (см. раздел Управление node_modules). Система разрешений Deno применяется и к коду CommonJS: обычно нужны -R (--allow-read) и -E (--allow-env), поскольку Deno проверяет файлы package.json и каталог node_modules при разрешении модулей CommonJS.

Как Deno определяет, что файл относится к CommonJS

Если расширение файла — .cjs, Deno считает модуль CommonJS, не проверяя package.json.

Deno также попытается загрузить файлы .js, .jsx, .ts и .tsx как CommonJS, если рядом с файлом или выше по дереву каталогов находится файл package.json с параметром "type": "commonjs". Это относится к проектам с файлом package.json:

package.json
{
  "type": "commonjs"
}
main.js
const express = require("express");

Сборщики Next.js и другие инструменты автоматически создают такой файл package.json. Если в существующем проекте используются модули CommonJS, можно обеспечить его работу и в Node.js, и в Deno, добавив параметр "type": "commonjs" в файл package.json.

В остальных случаях Deno не анализирует содержимое модулей для обнаружения CommonJS, поскольку поиск файлов package.json в файловой системе и анализ модуля на предмет CommonJS занимают больше времени, чем отказ от такой проверки, а также не поощряют использование CommonJS. В Deno >= 2.1.2 это обнаружение можно включить флагом --unstable-detect-cjs. Он действует, если только в файле package.json не задано { "type": "module" }.

Вызов require() из модуля ES

Экземпляр функции require() можно создать вручную:

main.js
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const express = require("express");

В этом случае действуют те же требования, что и при запуске файлов .cjs: зависимости нужно установить вручную, а также указать подходящие флаги разрешений.

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

Реализация require() в Deno поддерживает подключение модулей ES через require. Это работает так же, как в Node.js: можно require() только модули ES, в графе зависимостей которых нет await на верхнем уровне. Иными словами, можно require() только «синхронные» модули ES.

greet.js
export function greet(name) {
  return `Hello ${name}`;
}
esm.js
import { greet } from "./greet.js";

export { greet };
main.cjs
const esm = require("./esm");
console.log(esm);
console.log(esm.greet("Deno"));
$ deno run -R main.cjs
[Module: null prototype] { greet: [Function: greet] }
Hello Deno

Работает и обратный вариант. В модулях ES можно импортировать файлы CommonJS:

greet.cjs
module.exports = {
  hello: "world",
};
main.js
import greet from "./greet.cjs";
console.log(greet);
$ deno run main.js
{ hello: "world" }

Если не работает: Deno подскажет, если файл похож на CommonJS, но загружается не как CommonJS. При загрузке файла .js, использующего require, в проекте "type": "module" сама ошибка подскажет, как это исправить:

›_
$ deno run main.js
error: Uncaught (in promise) ReferenceError: require is not defined
const os = require("node:os");
           ^
    at file:///my-app/main.js:1:12

    info: Deno supports CommonJS modules in .cjs files, or when the closest
          package.json has a "type": "commonjs" option.
    hint: Rewrite this module to ESM,
          or change the file extension to .cjs,
          or add package.json next to the file with "type": "commonjs" option,
          or pass --unstable-detect-cjs flag to detect CommonJS when loading.
    docs: https://docs.deno.com/go/commonjs

Если вы видите ошибку о том, что module или require не определен, подойдет одно из четырех решений:

  • Переписать код с использованием ESM
  • Изменить расширение файла на .cjs
  • Добавить рядом файл package.json с параметром { "type": "commonjs" }
  • Запустить с флагом --unstable-detect-cjs

Управление node_modules

При запуске npm install npm создает в проекте каталог node_modules, в котором хранятся зависимости, указанные в файле package.json. По умолчанию Deno разрешает пакеты npm из центрального глобального кэша и не создает каталог node_modules. Такой подход занимает меньше места, сохраняет чистоту каталога проекта и рекомендуется для новых проектов Deno.

Однако иногда в проекте Deno необходим локальный каталог node_modules, даже если у вас нет package.json (например, при использовании фреймворков Next.js или Svelte либо при наличии зависимостей npm, использующих Node-API).

Выбор режима node_modules

Режим Когда использовать Как включить
none Большинство проектов Deno; репозиторий остается чистым По умолчанию; ничего не нужно делать
auto Инструменты и сборщики ожидают node_modules; Node-API "nodeModulesDir": "auto" или --node-modules-dir=auto
manual Существующий package.json с этапом установки "nodeModulesDir": "manual" + запуск deno install/npm/pnpm
Примечание

Рекомендуем использовать режим none по умолчанию и переходить на режим auto или manual, если возникают ошибки о недостающих пакетах в каталоге node_modules.

Автоматическое создание node_modules

Если в проекте нужен каталог node_modules, можно указать флаг --node-modules-dir=auto для отдельной команды или параметр "nodeModulesDir": "auto" в файле конфигурации, чтобы Deno создал каталог node_modules в текущем рабочем каталоге:

›_
deno run --node-modules-dir=auto main.ts

либо использовать файл конфигурации:

deno.json
{
  "nodeModulesDir": "auto"
}

В автоматическом режиме зависимости устанавливаются в глобальный кэш, а в корне проекта создается локальный каталог node_modules. Этот режим рекомендуется для проектов с зависимостями npm, которым нужен каталог node_modules: главным образом для проектов со сборщиками или зависимостями npm со скриптами postinstall.

Ручное создание node_modules

Если в проекте есть файл package.json, можно использовать ручной режим, в котором для создания каталога node_modules нужно выполнить установку:

›_
deno install
deno run --node-modules-dir=manual main.ts

либо использовать файл конфигурации:

deno.json
{ "nodeModulesDir": "manual" }

Затем выполните deno install/npm install/pnpm install или используйте другой менеджер пакетов, чтобы создать каталог node_modules.

Ручной режим используется по умолчанию в проектах с package.json. Возможно, этот порядок действий вам знаком по проектам Node.js. Он рекомендуется для проектов с такими фреймворками, как Next.js, Remix, Svelte, Qwik и т. д., или такими инструментами, как Vite, Parcel или Rollup.

Выбор структуры: изолированная или поднятая

Если есть локальный каталог node_modules, Deno может организовать его содержимое двумя способами. В режиме по умолчанию (изолированном) каждый пакет устанавливается в адресуемый по содержимому каталог .deno/ и становится доступен через символическую ссылку, поэтому каждый пакет видит только объявленные для него зависимости. Такой подход похож на структуру pnpm.

node_modules/
├── .deno/chalk@5.6.2/node_modules/chalk/   ← real files
└── chalk -> .deno/chalk@5.6.2/node_modules/chalk

Некоторые инструменты npm, а также пакеты, которые обходят node_modules в поисках расположенных на одном уровне зависимостей, предполагают поднятую структуру, используемую npm и классическим Yarn. В Deno 2.8 появился поднятый режим (denoland/deno#32788), который можно включить с помощью nodeModulesLinker в deno.json. Для поднятого способа связывания модулей требуется каталог node_modules, управляемый вручную, поэтому установите nodeModulesDir в значение manual:

deno.json
{
  "nodeModulesDir": "manual",
  "nodeModulesLinker": "hoisted"
}

Или укажите флаг CLI для однократного запуска (также требуется --node-modules-dir=manual):

›_
deno install --node-modules-dir=manual --node-modules-linker=hoisted

В поднятом режиме версия каждого пакета с наибольшим количеством зависимостей размещается в корне node_modules/, а конфликтующие версии помещаются во вложенные каталоги зависимостей, которым они нужны, — так же, как в npm:

node_modules/
├── chalk/         ← real files
├── express/
├── ms/            ← hoisted: most commonly needed version
└── debug/
    └── node_modules/
        └── ms/    ← nested: a different version

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

Использование пакетов с нативными дополнениями

Deno поддерживает дополнения Node-API, используемые такими популярными пакетами npm, как esbuild, npm:sqlite3 и npm:duckdb. Пакеты, использующие публичные API Node-API, должны работать.

Начиная с Deno 2.0 поддерживаются пакеты npm с дополнениями Node-API, если присутствует локальный каталог node_modules/. Настройте "nodeModulesDir": "auto" | "manual" в deno.json или запустите программу с флагом --node-modules-dir=auto|manual. И, как и для любого нативного FFI, укажите --allow-ffi, чтобы явно предоставить разрешение. См. раздел «Безопасность и разрешения».

Если не работает: многие дополнения полагаются на скрипты жизненного цикла npm (например, postinstall) для сборки или загрузки нативной привязки, а Deno по соображениям безопасности не запускает такие скрипты по умолчанию. При установке такого пакета выводится предупреждение:

›_
$ deno install npm:duckdb
╭ Warning
│
│  Ignored build scripts for packages:
│  npm:duckdb@1.4.4
│
│  Run "deno approve-scripts" to run build scripts.
╰─

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

›_
$ deno run -R -E --allow-ffi main.mjs
error: Uncaught (in promise) Error: Cannot find module '/my-app/node_modules/.deno/duckdb@1.4.4/node_modules/duckdb/lib/binding/duckdb.node'

Чтобы исправить это, разрешите скрипты конкретного пакета (или выполните интерактивную команду deno approve-scripts):

›_
$ deno install --allow-scripts=npm:duckdb
Initialize duckdb@1.4.4: running 'install' script

$ deno run -R -E --allow-ffi main.mjs
[ { answer: 42 } ]

Все параметры скриптов жизненного цикла описаны в документации deno install.

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

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

["deno", "node", "import", "module-sync", "default"]

Это означает, что будет выбрано первое условие в экспорте пакета, ключ которого совпадает с любой из этих строк. При разрешении require(), включая createRequire(), используются следующие условия:

["require", "node", "module-sync", "default"]

Deno также применяет module-sync при анализе модулей CommonJS, повторно экспортирующих модули через require().

Список условий импорта можно расширить с помощью флага CLI --conditions:

deno run --conditions development,react-server main.ts
[
  "development",
  "react-server",
  "deno",
  "node",
  "import",
  "module-sync",
  "default"
]

Получение определений типов Node и npm

Начиная с Deno 2.8, deno check и LSP по умолчанию включают lib.node в каждую проверку типов, поэтому глобальные типы Node, такие как Buffer, NodeJS.Timeout и process, доступны без какой-либо настройки:

// 2.8+: type-checks with no extra setup
const buf: Buffer = Buffer.from("hello");
const t: NodeJS.Timeout = setTimeout(() => {}, 0);

Встроенный пакет lib.node отслеживает основную версию @types/node, соответствующую выпуску Node, версию которого Deno указывает в process.versions.node. Если нужно зафиксировать конкретную версию @types/node (например, чтобы она соответствовала версии Node, принятой в проекте), добавьте ее как явную зависимость:

deno.json
{
  "imports": {
    "@types/node": "npm:@types/node@^22"
  }
}

В версиях до 2.8 или если отключен параметр lib.node типы по-прежнему можно загрузить с помощью директивы reference:

/// <reference types="npm:@types/node" />

С помощью той же директивы можно использовать типы из пространства имен NodeJS, например BufferEncoding, в собственных сигнатурах:

buffer-types.ts
/// <reference types="npm:@types/node" />

// Now you can use NodeJS namespace types
function writeToBuffer(data: string, encoding: NodeJS.BufferEncoding): Buffer {
  return Buffer.from(data, encoding);
}

Типы для пакетов npm

Многие пакеты npm содержат типы: их можно импортировать и сразу же использовать:

import chalk from "npm:chalk@5";

Некоторые пакеты не содержат типы, но их можно указать с помощью директивы @ts-types. Например, можно использовать пакет @types:

// @ts-types="npm:@types/express@^4.17"
import express from "npm:express@^4.17";

Если типы пакета выглядят неверно

Официальный компилятор TypeScript tsc поддерживает различные настройки moduleResolution. Deno поддерживает только современное разрешение node16. К сожалению, многие пакеты npm не предоставляют типы корректно при разрешении модулей node16, из-за чего deno check может сообщать об ошибках типов, о которых tsc не сообщает.

Если тип экспорта по умолчанию из импорта npm: кажется неверным (при этом правильный тип, по всей видимости, доступен в свойстве .default), скорее всего, пакет предоставляет неверные типы при разрешении модулей node16 для импортов из ESM. Это можно проверить, выяснив, возникает ли ошибка также с tsc --module node16 и "type": "module" в package.json, или обратившись к сайту Are the types wrong? (в частности, к строке «node16 from ESM»).

Если вы хотите использовать пакет, который не поддерживает разрешение модулей TypeScript node16, можно:

  1. Создать обращение об этой проблеме в системе отслеживания ошибок пакета. (И, возможно, внести исправление :) (К сожалению, пакеты пока плохо обеспечены инструментами для поддержки одновременно ESM и CJS, поскольку для экспортов по умолчанию требуются разные синтаксические конструкции. См. также microsoft/TypeScript#54593.)
  2. Вместо идентификатора npm: использовать CDN, который пересобирает пакеты для поддержки Deno.
  3. Игнорировать ошибки типов, возникающие в вашей кодовой базе, с помощью // @ts-expect-error или // @ts-ignore.

Приватные реестры

Внимание

Не путайте их с приватными репозиториями и модулями.

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

Что такое приватные реестры?

Крупные организации часто размещают собственные приватные реестры npm для безопасного управления внутренними пакетами. Такие приватные реестры служат хранилищами, в которых организации могут публиковать и хранить собственные или специально разработанные пакеты. В отличие от публичных реестров npm, приватные реестры доступны только авторизованным пользователям внутри организации.

Как использовать приватные реестры с Deno

Сначала настройте файл .npmrc, указав в нём свой приватный реестр. Файл .npmrc должен находиться в корне проекта или в каталоге $HOME. Добавьте в файл .npmrc следующее:

›_
@mycompany:registry=http://mycompany.com:8111/
//mycompany.com:8111/:_authToken=secretToken

Замените http://mycompany.com:8111/ фактическим URL вашего приватного реестра, а secretToken — токеном аутентификации. _authToken — это стандартный формат токена Bearer; также поддерживаются реестры, использующие устаревшие учётные данные _auth (см. список возможностей .npmrc ниже).

Затем обновите ваш deno.json или package.json, указав путь импорта для приватного пакета. Например:

deno.json
{
  "imports": {
    "@mycompany/package": "npm:@mycompany/package@1.0.0"
  }
}

или, если вы используете package.json:

package.json
{
  "dependencies": {
    "@mycompany/package": "1.0.0"
  }
}

Теперь вы можете импортировать приватный пакет в код Deno:

main.ts
import { hello } from "@mycompany/package";

console.log(hello());

и запустить его с помощью команды deno run:

›_
deno run main.ts

Конфигурация .npmrc

Помимо описанной выше базовой настройки реестра и токена, Deno считывает несколько других полей .npmrc. Наиболее важные из них:

  • Взаимная TLS-аутентификация (Deno 2.8+): certfile и keyfile указывают на PEM-файлы, используемые для аутентификации клиента, когда реестр требует mTLS.

    .npmrc
    //registry.mycompany.com/:certfile=/etc/deno/client.crt
    //registry.mycompany.com/:keyfile=/etc/deno/client.key
    
  • email в записях _auth (Deno 2.8+): некоторые устаревшие локальные реестры требуют email наряду с токеном аутентификации.

    .npmrc
    //registry.mycompany.com/:_auth=secretToken
    //registry.mycompany.com/:email=ci@mycompany.com
    
  • min-release-age: запрещает устанавливать версии пакетов, опубликованные позднее заданного срока, в качестве меры защиты цепочки поставок. Начиная с Deno 2.9 по умолчанию применяется минимальный срок в 24 часа, даже если он не задан, поэтому недавно опубликованные версии автоматически пропускаются. Чтобы изменить этот период, укажите явное значение, а чтобы отключить ограничение — 0. Эту настройку также можно задать с помощью флага CLI --minimum-dependency-age, поля minimumDependencyAge в deno.json и переменной среды NPM_CONFIG_MIN_RELEASE_AGE. Подробности см. в разделе Минимальный возраст зависимости.

    .npmrc
    min-release-age=3
    
  • trust-policy: при использовании no-downgrade запрещает разрешение версии пакета, уровень доверия к публикации которой (доверенная публикация, подтверждение происхождения или поэтапная публикация) ниже уже записанного в файле блокировки. По умолчанию отключено. Подробности см. в разделе Политика доверия к публикациям.

    .npmrc
    trust-policy=no-downgrade
    
  • Переменная среды NPM_CONFIG_REGISTRY: переопределяет реестр, заданный в .npmrc, в соответствии с приоритетом npm (удобно в CI, если нужно перенаправить установку пакетов, не изменяя файл .npmrc, хранящийся в системе контроля версий).

Зависимости file: и link: в опубликованных пакетах

В некоторых опубликованных пакетах npm по ошибке указывается спецификатор file: или link: в файле package.json, ссылающийся на путь на компьютере автора пакета:

some-package/package.json
{
  "dependencies": {
    "lodash": "^4.17.0",
    "local-helpers": "file:../local-helpers"
  }
}

Начиная с Deno 2.8 такие записи file: и link: пропускаются при разрешении метаданных npm, поэтому пакеты со случайно указанной зависимостью на локальный путь устанавливаются без ошибок, вместо того чтобы завершаться с ошибкой «Invalid version requirement».

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

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

Spec-Zone.ru

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