Совместимость Node и npm
Большая часть кода Node.js работает в Deno без изменений. Вот стандартный HTTP-сервер Node, запущенный с помощью deno вместо node:
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: и запустите файл:
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::
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.jsconsole.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 fileDeno сообщает текущую версию, совместимую с Node:
process.version— этоv26.3.0, аprocess.versions.napi—10(версия Node-API 10), поэтому пакеты, проверяющие версию Node или Node-API, видят современную среду выполнения. -
Bufferнеобходимо явно импортировать из модуляnode:buffer:buffer.jsimport { 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.jsTimeout, а не число, что соответствует семантике 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 запускается двумя командами: одной для установки, другой для запуска.
{
"type": "module",
"scripts": {
"start": "node main.js"
},
"dependencies": {
"chalk": "^5"
}
}
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:
{
"nodeModulesDir": "auto"
}
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:
{
"type": "commonjs"
}
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() можно создать вручную:
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.
export function greet(name) {
return `Hello ${name}`;
}
import { greet } from "./greet.js";
export { greet };
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:
module.exports = {
hello: "world",
};
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
либо использовать файл конфигурации:
{
"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
либо использовать файл конфигурации:
{ "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:
{
"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, принятой в проекте), добавьте ее как явную зависимость:
{
"imports": {
"@types/node": "npm:@types/node@^22"
}
}
В версиях до 2.8 или если отключен параметр lib.node типы по-прежнему можно загрузить с помощью директивы reference:
/// <reference types="npm:@types/node" />
С помощью той же директивы можно использовать типы из пространства имен NodeJS, например BufferEncoding, в собственных сигнатурах:
/// <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, можно:
- Создать обращение об этой проблеме в системе отслеживания ошибок пакета. (И, возможно, внести исправление :) (К сожалению, пакеты пока плохо обеспечены инструментами для поддержки одновременно ESM и CJS, поскольку для экспортов по умолчанию требуются разные синтаксические конструкции. См. также microsoft/TypeScript#54593.)
- Вместо идентификатора
npm:использовать CDN, который пересобирает пакеты для поддержки Deno. - Игнорировать ошибки типов, возникающие в вашей кодовой базе, с помощью
// @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, указав путь импорта для приватного пакета. Например:
{
"imports": {
"@mycompany/package": "npm:@mycompany/package@1.0.0"
}
}
или, если вы используете package.json:
{
"dependencies": {
"@mycompany/package": "1.0.0"
}
}
Теперь вы можете импортировать приватный пакет в код Deno:
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. Подробности см. в разделе Минимальный возраст зависимости..npmrcmin-release-age=3 -
trust-policy: при использованииno-downgradeзапрещает разрешение версии пакета, уровень доверия к публикации которой (доверенная публикация, подтверждение происхождения или поэтапная публикация) ниже уже записанного в файле блокировки. По умолчанию отключено. Подробности см. в разделе Политика доверия к публикациям..npmrctrust-policy=no-downgrade -
Переменная среды
NPM_CONFIG_REGISTRY: переопределяет реестр, заданный в.npmrc, в соответствии с приоритетом npm (удобно в CI, если нужно перенаправить установку пакетов, не изменяя файл.npmrc, хранящийся в системе контроля версий).
Зависимости file: и link: в опубликованных пакетах
В некоторых опубликованных пакетах npm по ошибке указывается спецификатор file: или link: в файле package.json, ссылающийся на путь на компьютере автора пакета:
{
"dependencies": {
"lodash": "^4.17.0",
"local-helpers": "file:../local-helpers"
}
}
Начиная с Deno 2.8 такие записи file: и link: пропускаются при разрешении метаданных npm, поэтому пакеты со случайно указанной зависимостью на локальный путь устанавливаются без ошибок, вместо того чтобы завершаться с ошибкой «Invalid version requirement».
Последнее обновление:
© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/runtime/fundamentals/node