On this page
Node 和 npm 兼容性
-
Deno 兼容 Node。大多数 Node 项目可以在 Deno 中运行,几乎不需要更改!
-
Deno 支持 npm 包。只需在导入时使用
npm:说明符,Deno 会处理其余部分。
例如,在 Deno 项目中,您可以这样从 npm 导入 Hono:
import { Hono } from "npm:hono";
这就是你开始所需了解的全部!但是,在这两个运行时之间有一些关键差异,你可以利用这些差异在将你的 Node.js 项目迁移到 Deno 时使代码更简单、更小。
截至 Deno 2.8,Node 自身测试套件中超过 75% 的测试在 Deno 中通过,覆盖了几乎所有 node: 模块。你可以在
node-test-viewer.deno.dev 追踪当前状态。
我们提供了一个 受支持的 Node.js API 列表 ,您可以在 Deno 中使用它们。
导入一个 npm 包 Jump to heading
import chalk from "npm:chalk@5";
console.log(chalk.green("Hello from npm in Deno"));
deno run main.ts
执行 CommonJS Jump to heading
使用 .cjs 扩展名告诉 Deno 该模块使用的是 CommonJS 系统。
const chalk = require("chalk");
console.log(chalk.green("Hello from npm in Deno"));
deno run main.cjs
使用 Node API Jump to heading
import path from "node:path";
console.log(path.join("./foo", "../bar"));
使用 Node 的内置模块 Jump to heading
Deno 提供了一个兼容层,允许在 Deno 程序中使用 Node.js 的内置 API。要使用它们,您需要在任何使用这些 API 的导入语句中添加 node: 前缀:
import * as os from "node:os";
console.log(os.cpus());
然后通过 deno run main.mjs 运行,您会注意到它与在 Node.js 中运行程序时输出相同。
更新您应用程序中的任何导入以使用 node: 前缀,应该能使任何使用 Node 内置 API 的代码照常工作。
为了方便更新现有代码,Deno 会为未使用 node: 前缀的导入提供有用的提示:
import * as os from "os";
console.log(os.cpus());
$ deno run main.mjs
error: Relative import path "os" not prefixed with / or ./ or ../
hint: If you want to use a built-in Node module, add a "node:" prefix (ex. "node:os").
at file:///main.mjs:1:21
相同的提示和其他快速修复也由 Deno LSP 在您的编辑器中提供。
node:module 内置模块包含
registerHooks() API,您可以使用它来自定义程序内部的模块解析和加载。
使用 npm 包 Jump to heading
Deno 原生支持通过使用 npm: 前缀导入 npm 包。例如:
import * as emoji from "npm:node-emoji";
console.log(emoji.emojify(`:sauropod: :heart: npm`));
可以通过以下命令运行:
$ deno run main.js
🦕 ❤️ npm
在执行 deno run 命令之前,不需要 npm install,也无需创建 node_modules 文件夹。这些包同样受到与 Deno 中其他代码相同的权限约束。
npm 前缀的格式如下:
npm:[@][/]
这也允许一些可能与 npx 命令相似的功能。
# npx 允许从 npm 或 URL 远程执行包
$ npx create-next-app@latest
# deno run 允许从各种位置远程执行包,
# 并可以通过 `npm:` 说明符限定为 npm。
$ deno run -A npm:create-next-app@latest
有关流行库的示例,请参考 教程部分。
一流的 package.json 支持 Jump to heading
Deno 了解您项目中的 package.json。您可以:
-
在那里声明依赖项(作为补充或替代内联的
npm:说明符)。 -
通过
deno task使用package.json中的脚本(例如,deno task start)。 -
在解析模块时依赖
package.json字段,如type(见下方的 CommonJS 支持)。 -
process- Deno 提供了process全局对象,这在流行的 npm 包中是迄今最常用的全局对象。它对所有代码都可用。Deno 也可以引导您显式地从node:process导入它。通过启用no-process-globallint 规则来选择启用(自 Deno 2.8 起默认关闭):
模块解析 Jump to heading
官方 TypeScript 编译器 tsc 支持不同的 moduleResolution 设置。Deno 仅支持现代的 node16 解析。不幸的是,许多 npm 包在 node16 模块解析下未能正确提供类型,可能会导致 deno check 报告类型错误,而 tsc 不报告这些错误。
如果 npm: 导入的默认导出似乎具有错误类型(正确的类型似乎在 .default 属性下),很可能是该包在从 ESM 的 node16 模块解析下提供了错误的类型。您可以通过检查是否在 tsc --module node16 和 package.json 中 "type": "module" 时也发生错误来验证,或通过访问 类型错误吗? 网站(特别是在 “从 ESM 的 node16” 行)。
如果您想使用不支持 TypeScript node16 模块解析的包,您可以:
- 在该包的问题跟踪器上打开一个问题报告。(或许可以贡献一个修复 :))不幸的是,由于包需要支持 ESM 和 CJS 缺乏工具,默认导出需要不同的语法。参见 microsoft/TypeScript#54593
- 使用一个 CDN,该 CDN 为 Deno 支持重建包,而不是使用
npm:标识。 - 使用
// @ts-expect-error或// @ts-ignore忽略您代码库中出现的类型错误。
包含 Node 类型 Jump to heading
Node 附带许多内置类型,如 Buffer,这些类型可能在 npm 包的类型中引用。要加载这些类型,您必须向 @types/node 包添加类型引用指令:
/// <reference types="npm:@types/node" />
注意,在大多数情况下,不指定版本通常是可以的,因为 Deno 将尝试与其内部的 Node 代码保持同步,但如果必要,您可以始终覆盖使用的版本。
CommonJS 支持 Jump to heading
CommonJS 是一种在ES 模块之前就存在的模块系统。尽管我们坚定地相信 ES 模块是 JavaScript 的未来,但依然存在数以百万计的使用 CommonJS 编写的 npm 库,而 Deno 提供了对它们的全面支持。Deno 将自动确定一个包是否使用 CommonJS,并在导入时无缝工作:
-
setTimeout/setInterval- 从 Deno 2.8 开始,全局定时器函数返回一个 Node.jsTimeout对象,而不是数字,行为与 Node.js 语义一致。返回的对象暴露了诸如.ref()、.unref()、.refresh()和.hasRef()之类的方法。它仍然可以通过Symbol.toPrimitive强制转换为数字,因此将定时器 ID 存储为数字或将其传递给clearTimeout/clearInterval的现有代码仍可保持不变地工作。const t = setTimeout(() => {}, 1000); t.unref(); // 不要让这个定时器保持事件循环存活 clearTimeout(t);
CommonJS 支持 Jump to heading
Deno 强烈建议在您的代码中使用 ES 模块,但也支持 CommonJS,具有以下限制:
在使用 CommonJS 模块时 Deno 的权限系统仍然有效。 可能需要提供至少 --allow-read 权限,因为 Deno 将探测文件系统中的 package.json 文件和 node_modules 目录,以正确解析 CommonJS 模块。
使用 .cjs 扩展名 Jump to heading
如果文件扩展名为 .cjs,Deno 将把该模块视为 CommonJS。
const express = require("express");
Deno 不会查看 package.json 文件和 type 选项来判断文件是 CommonJS 还是 ESM。
在使用 CommonJS 时,Deno 期望依赖项将手动安装,并且将存在一个 node_modules 目录。最好在您的 deno.json 中设置 "nodeModulesDir": "auto" 以确保这一点。
$ cat deno.json
{
"nodeModulesDir": "auto"
}
$ deno install npm:express
Add npm:express@5.0.0
$ deno run -R -E main.cjs
[Function: createApplication] {
application: {
init: [Function: init],
defaultConfiguration: [Function: defaultConfiguration],
...
}
}
-R 和 -E 标志用于允许权限读取文件和环境变量。
您也可以直接运行 .cjs 文件:
deno run -A main.cjs
package.json type 选项 Jump to heading
如果存在与该文件相邻的 package.json 文件,并且具有选项 "type": "commonjs",Deno 将尝试将 .js、.jsx、.ts 和 .tsx 文件作为 CommonJS 加载。
{
"type": "commonjs"
}
const express = require("express");
像 Next.js 的打包工具等工具将自动生成这样的 package.json 文件。
如果您有一个已存在的使用 CommonJS 模块的项目,可以通过向 package.json 文件添加 "type": "commonjs" 选项,使其与 Node.js 和 Deno 一起工作。
始终检测文件是否可能是 CommonJS Jump to heading
通过在 Deno >= 2.1.2 中使用 --unstable-detect-cjs 运行,您可以告诉 Deno 分析模块是否可能是 CommonJS。除非存在一个带有 { "type": "module" } 的 package.json 文件,否则该设置将生效。
在文件系统中查找 package.json 文件并分析模块以检测它是否是 CommonJS 会比不这样做耗时。因此,为了避免使用 CommonJS,Deno 默认不执行此行为。
手动创建 require() Jump to heading
替代的方法是手动创建 require() 函数的实例:
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
const express = require("express");
在这种情况下,将适用与运行 .cjs 文件时相同的要求——需要手动安装依赖项并授予适当的权限标志。
require(ESM) Jump to heading
Deno 的 require() 实现支持要求 ES 模块。
这与 Node.js 中的工作方式相同,您只能 require() 其模块图中没有顶级 await 的 ES 模块——或者换句话说,您只能 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
导入 CommonJS 模块 Jump to heading
您还可以在 ES 模块中导入 CommonJS 文件。
module.exports = {
hello: "world",
};
import greet from "./greet.js";
console.log(greet);
$ deno run main.js
{
"hello": "world"
}
提示和建议 Jump to heading
Deno 会提供有用的提示和建议,指导您在处理 CommonJS 模块时如何编写有效代码。
例如,如果您尝试运行没有 .cjs 扩展名的 CommonJS 模块,或没有带有 { "type": "commonjs" } 的 package.json,您可能会看到:
error ReferenceError: module is not defined
解决方法包括:
- 重写为 ES 模块
- 将文件扩展改为
.cjs - 添加带
{ "type": "commonjs" }的相邻package.json - 使用
--unstable-detect-cjs标志运行
详见文档:Deno 中的 CommonJS
条件导出(Conditional exports) Jump to heading
包的导出可以根据解析模式进行条件判断。从 Deno ESM 模块导入满足的条件如下:
["deno", "node", "import", "default"]
这意味着在包导出中键等于这些字符串中的任意一个时,将匹配第一个出现的条件。您可以使用 --unstable-node-conditions CLI 标志扩展此列表:
deno run --conditions development,react-server main.ts
此时满足的条件列表变为:
["development", "react-server", "deno", "node", "import", "default"]
导入类型 Jump to heading
许多 npm 包带有类型,您可以导入这些类型并直接使用:
import chalk from "npm:chalk@5";
一些包不随附类型,但您可以使用 @ts-types 指令指定它们的类型。例如,使用 @types 包:
// @ts-types="npm:@types/express@^4.17"
import express from "npm:express@^4.17";
运行 npm CLI 工具 Jump to heading
官方 TypeScript 编译器 tsc 支持不同的
moduleResolution
设置。Deno 仅支持现代的 node16 解析。不幸的是,许多
npm 包在 node16 模块解析下未能正确提供类型,
这可能会导致 deno check 报告类型错误,而 tsc 不会报告这些错误。
如果 npm: 导入的默认导出似乎具有错误类型(正确的
类型似乎在 .default 属性下),那么最有可能的情况是,该包为
从 ESM 导入时的 node16 模块解析提供了错误的类型。您可以通过检查错误是否也会在
tsc --module node16 且 package.json 中为 "type": "module" 时发生,或者查阅
类型错误吗? 网站
(尤其是 “从 ESM 的 node16” 那一行)来验证这一点。
如果您想使用不支持 TypeScript node16 模块 解析的包,您可以:
- 在该包的问题跟踪器上针对该问题打开一个 issue。(或许 还可以顺手贡献一个修复 :))不过,不幸的是,目前缺乏让包同时支持 ESM 和 CJS 的工具, 因为默认导出需要不同的语法。另请参见 microsoft/TypeScript#54593
- 使用一个 CDN,该 CDN 为
Deno 支持重建这些包,而不是使用
npm:标识符。 - 使用
// @ts-expect-error或// @ts-ignore忽略您代码库中遇到的类型错误。
包含 Node 类型 Jump to heading
从 Deno 2.8 开始,deno check 和 LSP 默认会在每次类型检查中包含 lib.node,因此像 Buffer、NodeJS.Timeout 和 process 这样的 Node 环境类型无需任何配置即可解析:
// 2.8+:无需额外设置即可通过类型检查
const buf: Buffer = Buffer.from("hello");
const t: NodeJS.Timeout = setTimeout(() => {}, 0);
捆绑的 lib.node 会跟踪与 Deno 在 process.versions.node 中报告的 Node 发行版相匹配的 @types/node 主版本。如果您需要固定某个特定的 @types/node 版本(例如与项目标准化使用的 Node 版本一致),请将其作为显式依赖添加:
{
"imports": {
"@types/node": "npm:@types/node@^22"
}
}
在 2.8 之前的版本中——或者如果您选择不使用 lib.node——您仍然可以通过引用指令加载这些类型:
/// <reference types="npm:@types/node" />
运行 npm 二进制文件 Jump to heading
您可以使用 npm: 标识符直接运行 npm CLI 工具(带有 bin 条目的包),而无需执行 npm install:
npm:[@][/]
例如:
$ deno run --allow-read npm:cowsay@1.5.0 "Hello there!"
______________
< Hello there! >
--------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
$ deno run --allow-read npm:cowsay@1.5.0/cowthink "What to eat?"
______________
( What to eat? )
--------------
o ^__^
o (oo)\_______
(__)\ )\/\
||----w |
|| ||
node_modules Jump to heading
当您运行 npm install 时,npm 会在您的项目中创建一个 node_modules 目录,其中存放 package.json 文件中指定的依赖项。
Deno 使用 npm 指定符 将 npm 包解析到中心的全局 npm 缓存,而不是在您的项目中使用 node_modules 文件夹。这是理想的,因为它占用更少的空间,并保持您的项目目录整洁。
然而,可能会有一些情况下,即使您没有 package.json,也需要在 Deno 项目中有一个本地的 node_modules 目录(例如,当使用像 Next.js 或 Svelte 这样的框架或依赖于使用 Node-API 的 npm 包时)。
选择 node_modules 模式 Jump to heading
- 默认无本地 node_modules (none):大多数 Deno 项目使用,保持仓库整洁,无需设置。
- 自动 (auto):当某些工具需要 node_modules 或您依赖 Node-API 插件,且希望自动创建本地 node_modules。
- 手动 (manual):已有 package.json 且偏好明确安装步骤。
| 模式 | 何时使用 | 如何启用 |
|---|---|---|
| none | 大多数 Deno 项目;保持仓库干净 | 默认;无需操作 |
| auto | 工具/打包器需要 node_modules;使用 Node-API | deno.json 配置 "nodeModulesDir": "auto" 或 --node-modules-dir=auto |
| manual | 已有 package.json,喜欢显式安装步骤 | deno.json 配置 "nodeModulesDir": "manual" + 运行安装命令 |
默认 Deno 依赖行为 Jump to heading
默认情况下,deno run 命令不会创建 node_modules 目录,依赖项安装到全局缓存。这是面向新建 Deno 项目的推荐设置。
自动创建 node_modules Jump to heading
若需要在项目创建本地 node_modules,可使用命令行 --node-modules-dir=auto 标志,或在配置文件中设置 "nodeModulesDir": "auto"。
deno run --node-modules-dir=auto main.ts
或
{
"nodeModulesDir": "auto"
}
自动模式将依赖安装到全局缓存,同时在当前目录创建本地的 node_modules。适用于依赖本地 node_modules 的工具和打包器。
手动创建 node_modules Jump to heading
当项目有 package.json,可启用手动模式,需执行安装步骤来创建本地 node_modules:
deno install
deno run --node-modules-dir=manual main.ts
或
{ "nodeModulesDir": "manual" }
手动模式默认适用于使用 package.json 的项目。适合 Next.js、Remix、Svelte、Qwik 等框架项目,或使用 Vite、Parcel、Rollup 工具的项目。
建议首选默认的 none 模式,若遇缺少包错误,再回退到 auto 或 manual。
node_modules 标志 Jump to heading
可通过 --node-modules-dir 选项单次启用 node_modules 目录创建。
示例 main.ts:
import chalk from "npm:chalk@5";
console.log(chalk.green("Hello"));
运行:
deno run --node-modules-dir main.ts
运行时将于当前目录创建 node_modules 文件夹,结构类似 npm。
node_modules 布局:isolated 与 hoisted Jump to heading
当存在本地 node_modules 目录时,Deno 可以采用两种布局方式。默认的(isolated)会将每个包安装到一个内容寻址的 .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 classic 所采用的 hoisted 布局。Deno 2.8 新增了 hoisted 模式
(denoland/deno#32788),您可以通过 deno.json 中的 nodeModulesLinker 选择启用。hoisted 链接器要求使用手动管理的 node_modules 目录,因此请将 nodeModulesDir 设置为 manual:
{
"nodeModulesDir": "manual",
"nodeModulesLinker": "hoisted"
}
或者作为一次性的 CLI 标志(同样需要 --node-modules-dir=manual):
deno install --node-modules-dir=manual --node-modules-linker=hoisted
在 hoisted 模式下,每个包中最常被依赖的版本会被放置在 node_modules/ 顶层,而冲突的版本则嵌套在需要它们的依赖项下方,就像 npm 一样:
node_modules/
├── chalk/ ← real files
├── express/
├── ms/ ← hoisted: most commonly needed version
└── debug/
└── node_modules/
└── ms/ ← nested: a different version
除非您依赖的工具要求使用 hoisted 布局,否则请继续使用默认的 isolated 模式。isolated 模式能够捕捉到 hoisted 布局会隐藏的虚假依赖。
Node-API 附加组件 Jump to heading
在 Node.js 中,有一些 全局对象 可用于所有程序的范围,这些对象特定于 Node.js,例如 process 对象。
以下是您可能在实际使用中遇到的一些全局对象以及如何在 Deno 中使用它们:
process- Deno 提供了process全局,这是最常用的全局对象,在流行的 npm 包中使用广泛。它对所有代码都是可用的。然而,Deno 会通过提供 lint 警告和快速修复指导您显式从node:process模块导入它:
console.log(process.versions.deno);
$ deno run process.js
2.0.0
$ 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
-
require()- 请参见 CommonJS 支持 -
Buffer- 要使用BufferAPI,必须显式从node:buffer模块导入:
import { Buffer } from "node:buffer";
const buf = new Buffer(5, "0");
对于需要 Node.js 特定类型如 BufferEncoding 的 TypeScript 用户,使用 @types/node 时,这些类型可以通过 NodeJS 命名空间获取:
/// <reference types="npm:@types/node" />
// 现在您可以使用 NodeJS 命名空间类型
function writeToBuffer(data: string, encoding: NodeJS.BufferEncoding): Buffer {
return Buffer.from(data, encoding);
}
更倾向于使用 Uint8Array 或其他 TypedArray 子类。
-
__filename- 使用import.meta.filename替代。 -
__dirname- 使用import.meta.dirname替代。
Node-API 插件 Jump to heading
Deno 支持 Node-API 插件,这些插件被流行的 npm 包使用,如 esbuild、npm:sqlite3 或 npm:duckdb。
您可以期望所有使用公共和文档 Node-API 的包都能正常工作。
大多数使用 Node-API 插件的包依赖于 npm “生命周期脚本”,如 postinstall。
虽然 Deno 支持它们,但出于安全考虑,默认情况下不执行这些脚本。请阅读 deno install 文档 了解更多信息。
自 Deno 2.0 以来,使用 Node-API 插件的 npm 包 仅在存在 node_modules/ 目录时支持。添加 "nodeModulesDir": "auto" 或 "nodeModulesDir": "manual" 设置到您的 deno.json 文件,或者使用 --node-modules-dir=auto|manual 标志运行,以确保这些包正常工作。在配置错误的情况下,Deno 会提供提示以说明如何解决此情况。
与所有原生 FFI 一样,您还必须传递 --allow-ffi 标志以显式授权 Node-API 插件在运行时沙箱之外运行。有关详细信息,请查看安全性和权限文档。
从 Node 迁移到 Deno Jump to heading
在 Deno 中运行您的 Node.js 项目是一个简单的过程。在大多数情况下,如果您的项目使用 ES 模块编写,您几乎不需要做任何更改。
需要注意的主要几点包括:
- 导入 Node.js 内置模块需要
node:前缀:
// ❌
import * as fs from "fs";
import * as http from "http";
// ✅
import * as fs from "node:fs";
import * as http from "node:http";
建议无论如何在您现有项目中更改这些导入前缀。这也是在 Node.js 中导入它们的推荐方式。
- 一些 在 Node.js 中可用的全局对象 需要显式导入,例如
Buffer:
import { Buffer } from "node:buffer";
require()仅在扩展名为.cjs的文件中可用,在其他文件中必须手动创建require()实例。npm 依赖可以在不考虑文件扩展名的情况下使用require()。
运行脚本 Jump to heading
Deno 原生支持通过 deno task 子命令运行 npm 脚本(如果您从 Node.js 迁移,这类似于 npm run script 命令)。考虑一个 Node.js 项目,其中在其 package.json 内有一个名为 start 的脚本:
{
"name": "my-project",
"scripts": {
"start": "eslint"
}
}
您可以通过运行以下命令在 Deno 中执行此脚本:
deno task start
可选改进 Jump to heading
Deno 的核心优势之一是统一的工具链,开箱即用地支持 TypeScript,以及包括 lint 工具、格式化工具和测试运行器在内的工具。切换到 Deno 使您能够简化工具链,减少项目中需要维护的组件数量。
配置
Deno 有自己的配置文件 deno.json 或 deno.jsonc,可用于配置您的项目。
您可以使用它通过 imports 选项定义依赖项——您可以逐个迁移 package.json 中的依赖项,或者选择在配置文件中完全不定义它们,而在代码中使用 npm: 前缀。
除了指定依赖项,您还可以使用 deno.json 定义任务、lint 和格式选项、路径映射以及其他运行时配置。
Lint 检查
Deno 自带一个内置 linter,性能优先考虑。它与 ESlint 类似,虽然规则数量有限。如果您不依赖于 ESLint 插件,您可以从 package.json 的 devDependencies 部分删除 eslint 依赖,并改为使用 deno lint。
Deno 可以在几毫秒内 lint 大型项目。您可以通过运行以下命令在项目上尝试:
deno lint
这将对您项目中的所有文件进行 lint。当 linter 检测到问题时,它将在您的编辑器和终端输出中显示该行。如下所示的示例:
error[no-constant-condition]: Use of a constant expressions as conditions is not allowed.
--> /my-project/bar.ts:1:5
|
1 | if (true) {
| ^^^^
= hint: Remove the constant expression
docs: https://docs.deno.com/lint/rules/no-constant-condition
Found 1 problem
Checked 4 files
许多 lint 问题可以通过传递 --fix 标志自动修复:
deno lint --fix
所有支持的 lint 规则的完整列表可以在 https://docs.deno.com/lint/ 找到。要了解更多关于如何配置 linter 的信息,请查看 deno lint 子命令。
格式化
Deno 配备了一个 内置格式化工具,可以选择根据 Deno 风格指南格式化您的代码。您可以取代将 prettier 添加到 devDependencies,而是使用 Deno 的内置零配置代码格式化器 deno fmt。
您可以通过运行以下命令在项目上运行格式化程序:
deno fmt
如果在 CI 中使用 deno fmt,也可以传递 --check 参数,当检测到格式不正确的代码时使格式化程序退出并显示错误。
deno fmt --check
格式化规则可以在您的 deno.json 文件中配置。要了解有关如何配置格式化程序的更多信息,请查看 deno fmt 子命令。
测试
Deno 鼓励为您的代码编写测试,并提供一个内置的测试运行器,使编写和运行测试变得容易。测试运行器与 Deno 紧密集成,因此您不需要额外的配置就能使 TypeScript 或其他功能正常工作。
Deno.test("my test", () => {
// 你的测试代码写在这里
});
deno test
传递 --watch 标志时,当导入的任何模块发生变化时,测试运行器将自动重新加载。
要了解有关测试运行器的更多信息以及如何配置它,请查看 deno test 子命令 文档。
私有仓库 Jump to heading
Deno 支持私有仓库,这允许您托管和共享自己的模块。这对于希望将其代码保持私密的组织或希望与特定人员分享代码的个人非常有用。
什么是私有仓库? Jump to heading
大型组织通常会托管自己的私有 npm 仓库,以安全地管理内部包。这些私有仓库作为存储库,通过它们组织可以发布和存储其专有或自定义包。与公共 npm 仓库不同,私有仓库仅对组织内的授权用户可访问。
如何在 Deno 中使用私有仓库 Jump to heading
首先,配置您项目中的 .npmrc 文件,以指向您的私有仓库。 .npmrc 文件必须位于项目根目录或 $HOME 目录中。在 .npmrc 文件中添加以下内容:
@mycompany:registry=http://mycompany.com:8111/
//mycompany.com:8111/:_auth=secretToken
将 http://mycompany.com:8111/ 替换为您的私有仓库的实际 URL,并将 secretToken 替换为您的身份验证令牌。
然后,更新您的 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 main.ts
.npmrc 配置 Jump to heading
除了上面的基本 registry / token 设置之外,Deno 还会读取其他几个 .npmrc
字段。最可能相关的是:
-
双向 TLS 身份验证(Deno 2.8+):
certfile和keyfile指向 用于在 registry 需要 mTLS 时对客户端进行身份验证的 PEM 文件。.npmrc//registry.mycompany.com/:certfile=/etc/deno/client.crt //registry.mycompany.com/:keyfile=/etc/deno/client.key -
_auth条目上的email(Deno 2.8+):某些传统的本地部署 registry 需要在 auth token 之外再提供一个email。.npmrc//registry.mycompany.com/:_auth=secretToken //registry.mycompany.com/:email=ci@mycompany.com -
min-release-age(Deno 2.8+):拒绝安装早于 配置年龄限制的包版本。对于所有安装来说,这对于默认的供应链防护很有用。同样的控制也可通过 CLI 标志--minimum-dependency-age和deno.json中的minimumDependencyAge字段使用。有关完整说明,请参阅 最小依赖年龄。.npmrcmin-release-age=3 -
NPM_CONFIG_REGISTRY环境变量:覆盖.npmrc中设置的 registry, 与 npm 的优先级规则一致(在 CI 中很方便,当您想在不编辑已提交的.npmrc的情况下重定向安装时)。
发布包中的 file: 和 link: 依赖 Jump to heading
某些已发布的 npm 包会意外地在其 package.json 中带上一个 file: 或 link: 说明符,
指向发布者机器上的某个路径:
{
"dependencies": {
"lodash": "^4.17.0",
"local-helpers": "file:../local-helpers"
}
}
从 Deno 2.8 开始,在解析 npm 元数据时,这些 file: 和 link: 条目会被静默跳过,
因此带有多余本地路径依赖的包可以顺利安装,而不会因
“Invalid version requirement” 错误而失败。
Node 到 Deno 速查表 Jump to heading
| Node.js | Deno |
|---|---|
node file.js |
deno file.js |
ts-node file.ts |
deno file.ts |
nodemon |
deno run --watch |
node -e |
deno eval |
npm i / npm install |
deno install |
npm install -g |
deno install -g |
npm run |
deno task |
eslint |
deno lint |
prettier |
deno fmt |
package.json |
deno.json 或 package.json |
tsc |
deno check ¹ |
typedoc |
deno doc |
jest / ava / mocha / tap / 等 |
deno test |
nexe / pkg |
deno compile |
npm explain |
deno info |
nvm / n / fnm |
deno upgrade |
tsserver |
deno lsp |
nyc / c8 / istanbul |
deno coverage |
| benchmarks | deno bench |
¹ 类型检查是自动进行的,TypeScript 编译器已内置在 deno 二进制文件中。