Deno 2.3:改进了 deno compile、本地 npm 包等
要升级到 Deno 2.3,请在终端中运行以下命令
deno upgrade
如果 Deno 尚未安装,请运行以下命令之一进行安装,或在此处了解如何安装。
# Using Shell (macOS and Linux):
curl -fsSL https://deno.land/install.sh | sh
# Using PowerShell (Windows):
iwr https://deno.land/install.ps1 -useb | iex
Deno 2.3 中的新功能
Deno 2.3 新增了多项功能,包括对 deno compile
和 deno fmt
等实用子命令的改进、对本地 npm 包的支持,以及 deno install
、LSP 等方面的多项性能提升。以下是您最想了解的功能列表:
- 改进的
deno compile
- 本地 npm 包
deno fmt
的改进deno add
的注册表标志- 更强大的 OpenTelemetry 支持
- Windows 上的代码签名
deno check
更直观的用法- 测试覆盖率改进
- Jupyter notebooks 中改进的类型检查
- 更快的依赖解析和安装
- 显式资源管理和
using
关键字 - 性能和 LSP
- TypeScript 5.8 和 V8 13.5
- 其他使用体验改进
- 致谢
deno compile
改进的 如果您还没有尝试过,deno compile
会将您的项目编译成单个二进制文件,从而无需安装 Deno 或依赖项即可轻松分发可运行程序。
Deno 2.3 扩展了 deno compile
,以支持使用外部函数接口 (FFI) 和 Node 本机插件的程序。这意味着编译后的 Deno 二进制文件可以包含并与本机库或 Node 插件一起工作。
// bcrypt requires Node native add-on
import * as bcrypt from "npm:bcrypt@5.1.1";
const password = "my-secure-password";
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
console.log(`bcrypt result: generated hash: ${hash}`);
const isMatch = await bcrypt.compare(password, hash);
console.log(`Password verification: ${isMatch ? "Success" : "Failed"}`);
使用以下命令编译上述代码:
deno compile --allow-ffi --allow-env main.ts
编译完成后,您可以运行该二进制文件:
$ ./main
bcrypt result: generated hash: $2b$10$IfAuXu/y8hWhwweaXZ8/suHb0JTxe2V4ABOsT1qPuBvxpg5/ITQ8W
Password verification: Success
此外,deno compile
现在能够从编译过程中排除特定文件,不将其嵌入。这使您可以更好地控制哪些文件被打包到独立可执行文件中。
通过排除不必要的文件以及将开发或测试文件从生产版本中排除,这有助于减小可执行文件的大小。
$ deno compile --include folder --exclude folder/sub_folder main.ts
2.3 还引入了一个新的 Deno.build.standalone
布尔值,用于指示代码是否在自包含的编译二进制文件中运行。这对于在特定构建环境中进行错误报告、功能切换、用户消息传递等非常有用。
console.log("Am I in a compiled binary?", Deno.build.standalone);
本地 npm 包
Deno 2.3 新增了对使用本地 npm 包的支持,使得在本地测试和开发 npm 包成为可能。
要使用本地 npm 模块,您需要一个本地 node_modules
文件夹,可以通过设置 "nodeModulesDir": "auto"
或 "nodeModulesDir": "manual"
来实现。(如果您选择后者,则每次更新本地 npm 包时都需要运行 deno install
。)
在 deno.json
的 patch
下添加本地 npm 包目录的路径
{
"patch": [
"../path/to/local_npm_package"
]
}
请注意,目前您的本地 npm 包名称也必须存在于 npm 注册表中。
deno fmt
的改进
Deno 2.3 将格式化标签模板中嵌入的 CSS、HTML 和 SQL
// CSS
const Div = styled.div`margin:
5px;
padding: ${padding} px;
`;
// HTML
document.body.innerHTML = html`
<main>
<h1>
Hello
${name}!
<h1></main>
`;
// SQL, with `--unstable-sql`
const query = sql`
SELECT ${table}.${field}
FROM
${table};
`;
// CSS
const Div = styled.div`
margin: 5px;
padding: ${padding}px;
`;
// HTML
document.body.innerHTML = html`
<main>
<h1>Hello ${name}!<h1>
</main>
`;
// SQL, with `--unstable-sql`
const query = sql`
SELECT
${table}.${field}
FROM
${table};
`;
此外,Deno 2.3 增加了对 14 个新的 deno fmt
选项的支持
bracePosition
jsx.bracketPosition
jsx.forceNewLinesSurroundingContent
jsx.multiLineParens
newLineKind
nextControlFlowPosition
operatorPosition
quoteProps
singleBodyPosition
spaceAround
spaceSurroundingProperties
trailingCommas
typeLiteral.separatorKind
useBraces
您可以在 deno.json
中设置格式化程序选项
{
"fmt": {
"quoteProps": "asNeeded",
"useBraces": "always",
"trailingCommas": "always"
}
}
deno add
的注册表标志
Deno 2.3 提供了一种新方法,通过新增 --npm
和 --jsr
注册表标志,分别从 npm 和 JSR 安装包。这在您需要在一个命令中添加来自给定注册表的多个包时特别有用。请注意,您仍然可以使用 specifier 添加依赖项。
# Install from different registries via specifiers.
deno add npm:react jsr:@std/fs
# With new `--npm` flag
deno add --npm chalk react
# Or the new `--jsr` flag
deno add --jsr @std/fs
# Or combine them as you like
deno add --npm chalk react jsr:@std/fs
更强大的 OpenTelemetry 支持
在 Deno 上一个次要版本中,我们引入了内置的 OpenTelemetry 支持,允许您自动从 Deno(或 Node.js)程序中捕获日志、指标和跟踪,并导出到您喜爱的数据可视化工具,例如 Grafana、Honeycomb 或 Hyperdx。
在 2.3 中,我们通过基础事件记录、span 上下文传播器、node:http
自动插桩和 V8 JS 引擎指标扩展了 Deno 的 OpenTelemetry 支持。让我们在下面深入了解每项内容。
基础事件记录
您现在可以将自定义事件附加到 span,从而通过更细粒度的详细信息和上下文改进调试。
// OpenTelemetry events with rich context for better observability
import { trace } from "npm:@opentelemetry/api@1";
await trace.getTracer("payment-service").startActiveSpan(
"processPayment",
async (span) => {
// Start of transaction with user context
span.addEvent("payment_initiated", {
userId: "user-123",
amount: 99.99,
currency: "USD",
});
// Track latency-sensitive operations
const startTime = performance.now();
await processPayment();
span.addEvent("payment_gateway_response", {
provider: "my-provider",
success: true,
});
span.end();
},
);
使用 span 上下文传播器在分布式服务中实现更好的跟踪
Deno 内置的 OpenTelemetry 支持会自动在日志和 span 之间保留跟踪上下文,因此您的跟踪表示单个请求,使其更容易理解。在 2.3 中,我们新增了在服务之间保留跟踪上下文的功能,从而可以在分布式系统中实现更简单的端到端跟踪。
请查看这个关于如何跟踪流经分布式服务的请求的教程。
node:http
客户端中的跟踪
Deno 内置 OpenTelemetry 支持的一个主要好处是,日志、跟踪和指标可以自动捕获,无需任何额外的代码更改。Deno 将自动对 console.log
、Deno.serve
和 fetch
进行插桩并导出遥测数据。
Deno 2.3 通过添加 node:http
模块扩展了自动插桩功能。使用 node:http
模块发出的 HTTP 请求将自动作为跟踪和指标导出到您的数据可视化工具。
V8 JS 引擎指标
Deno 2.3 的 OpenTelemetry 支持现在包括自动收集来自 V8 引擎的运行时指标,这对于监控程序的核心生命体征非常有用。
以下是在 Prometheus 中随时间可视化简单应用程序的 v8js_memory_heap_size_bytes
的示例:
Windows 上的代码签名
deno
可执行文件现在已在 Windows 上签名,这将使 Microsoft Defender 信任 Deno。这使得您可以在生产环境和 Windows 服务器上使用 Deno,因为它确保了您的二进制文件经过验证且值得信赖。
deno check
更直观的用法
Deno 完整的 JavaScript 和 TypeScript 工具链包括使用 deno check
进行类型检查。
您可以通过明确指定文件来对其进行类型检查,例如:deno check main.ts
。但现在,在 2.3 中,deno check
不再需要显式参数,其行为将类似于 deno check .
。这将使快速对整个目录进行类型检查变得更简单。
$ deno init
✅ Project initialized
Run these commands to get started
# Run the program
deno run main.ts
# Run the program and watch for file changes
deno task dev
# Run the tests
deno test
$ ls
deno.json main.ts main_test.ts
$ deno check
Check file:///dev/main.ts
Check file:///private/tmp/2.3/init/main_test.ts
测试覆盖率改进
此次次要版本对 Deno 的覆盖率报告生成器引入了三项使用体验改进,简化了操作并提高了灵活性。
测试中自动生成覆盖率报告
现在,使用 deno test --coverage
运行测试时,测试完成后会自动生成覆盖率报告。这通过消除单独的 deno coverage
步骤,简化了覆盖率工作流程。
# 2.2
$ deno test --coverage
$ deno coverage --lcov --output=lcov.info
$ deno coverage --html
# 2.3
$ deno test --coverage
# 2.3, opting out of report auto-generation
$ deno test --coverage --coverage-raw-data-only
DENO_COVERAGE_DIR
用于测试覆盖率的 一个新的 DENO_COVERAGE_DIR
环境变量决定了在使用 --coverage
标志时覆盖率信息的存储位置。您现在可以将覆盖率输出导向您选择的特定目录。
覆盖率忽略注释
Deno 的代码覆盖率工具现在可以识别特殊的“忽略”注释。您可以忽略单行、代码块以及整个文件。
// deno-coverage-ignore
console.log("This line is ignored");
// deno-coverage-ignore-start
if (condition) {
console.log("Both the branch and lines are ignored");
}
// deno-coverage-ignore-stop
// deno-coverage-ignore-file
console.log("All of the code in this file are ignored.");
这允许您将某些行或代码块从覆盖率报告中排除,这样它们就不会计入您的覆盖率指标。特别感谢 bcheidemann 的贡献。
Jupyter notebooks 中改进的类型检查
Deno 的 Jupyter 支持允许您不仅可以使用 JavaScript 和 TypeScript 探索和可视化数据,还可以将其用作升级版的 REPL 进行原型设计和尝试。使用 Deno 和 Jupyter 的最佳方式之一是结合 VSCode 的 Jupyter 扩展,它允许您在 VSCode 中创建和运行 Jupyter notebooks。
Deno 2.3 通过确保变量、模块和类型定义在 Jupyter 单元格之间共享,改进了 VSCode Jupyter 的体验。以前在 VSCode 中看起来无法识别的变量和类型定义现在将被识别。
更快的依赖解析和安装
在大多数 npm
依赖项已缓存的情况下,使用 deno install
和 deno add
安装依赖项现在速度大约快 2 倍。
- 在内存中缓存 npm 信息:这通过在执行期间将解析的 npm 包信息缓存到内存中,提高了包安装性能。Deno 避免多次重新读取和重新解析相同的数据,从而加快了安装速度。
- 防止重复缓存 npm 包:以前,在某些情况下,Deno 会在解析期间反复尝试缓存 npm 包。现在,Deno 将不会尝试重复缓存 npm 包,从而避免了冗余工作并显著加快了安装速度。
- 改进的 lockfile v5:新的 lockfile 格式包含额外的 npm 包元数据,以加快依赖项解析和安装。
使用 deno run -A npm:create-vite --template react-ts
生成的模板进行快速基准测试显示,运行 deno install
时速度提高了 2.5 倍。
$ hyperfine --warmup 5 -N --prepare "rm -rf node_modules" --setup "rm -rf deno.lock" "./deno-2.3 i" "./deno-2.2 i"
Benchmark 1: ./deno-2.3 i
Time (mean ± σ): 189.0 ms ± 19.1 ms [User: 59.6 ms, System: 221.9 ms]
Range (min … max): 167.0 ms … 221.3 ms 10 runs
Benchmark 2: ./deno-2.2 i
Time (mean ± σ): 474.8 ms ± 19.6 ms [User: 301.6 ms, System: 252.8 ms]
Range (min … max): 444.4 ms … 507.8 ms 10 runs
Summary
./deno-2.3 i ran
2.51 ± 0.27 times faster than ./deno-2.2 i
using
关键字
显式资源管理和 Deno 现在支持新的 JavaScript “显式资源管理”提案(例如 using
关键字),让您更轻松地管理和处置代码中的资源。请注意,此功能自 Deno v1.37 起已在 TypeScript 中受支持,但由于 V8 中的原生支持,现在已可在 JavaScript 中使用。
// 2.2
const file = Deno.createSync("data.txt");
try {
const encoder = new TextEncoder();
for (let i = 0; i < 100; i++) {
file.writeSync(encoder.encode(`${i}\n`));
}
} finally {
file.close();
}
// 2.3
{
using file = Deno.createSync("data.txt");
const encoder = new TextEncoder();
for (let i = 0; i < 100; i++) {
file.writeSync(encoder.encode(`${i}\n`));
}
}
性能和 LSP
Deno 2.3 也带来了一些性能改进:
Deno.serve
和 HTTP 服务器的速度得到提升,这得益于使用了更高的编译器优化级别。- 可静态分析的动态导入现在可以按需加载,从而提高启动性能。
此外,我们对 Deno 语言服务器也进行了一些性能改进:
- 通过在 Deno 启用文件打开时按需启动 TypeScript 服务器和按需注册语义令牌,减少空闲内存使用。
- 通过避免冗余的 npm 解析,提高了大型 monorepo 项目中 npm 依赖项的速度。
TypeScript 5.8 和 V8 13.5
Deno 2.3 升级到 TypeScript 5.8 和 V8 13.5,带来了新的语言特性和性能改进。
其他使用体验改进
此次次要版本还包括许多其他使用体验改进:
- 添加了对
FORCE_COLOR
环境变量的支持,以强制彩色终端输出 - 将标志
--permit-no-files
扩展到deno fmt
和deno lint
,如果未找到文件,则不会返回错误(适用于 CI) - Deno 程序可以通过 Linux vsock(虚拟套接字)进行通信
- 引入
DENO_SERVE_ADDRESS
环境变量,为deno serve
命令设置默认的host:port
- 添加了 WebGPU 方法
deviceStartCapture
和deviceStopCapture
- 在 lint 插件 API 中添加了对字段选择器(例如
.<field>
)的支持
致谢
没有社区的帮助,我们无法构建 Deno!无论是通过在我们的社区 Discord 服务器中回答问题还是报告 bug,我们都非常感谢您的支持。特别是,我们要感谢以下为 Deno 2.3 做出贡献的人们:0hmX, Adakite, Arsh, Asher Gomez, Ben Heidemann, Benjamin Swerdlow, Bert Belder, Dan, Dan Dascalescu, Dimitris Apostolou, Efe, Gene Parmesan Thomas, Gowtham K, Hajime-san, Jake Champion, James Bronder, Jim Buzbee, Kenta Moriuchi, KnorpelSenf, Lach, Laurence Rowe, Lucas Wasilewski, Luke Edwards, Manish Sahani, Max, Mohammad Sulaiman, MujahedSafaa, Muthuraj Ramalingakumar, Paolo Barbolini, Sebastien Guillemot, Toma, WWRS, c00kie17, chirsz, letianpailove, roman, and ryu。
您想加入 Deno 贡献者的行列吗?在此处查看我们的贡献文档,下次我们会在列表中看到您。
信不信由你,上面列出的更改仍然没有告诉您 2.3 中所有改进的地方。您可以在 GitHub 上查看 Deno 2.3 中合并的完整拉取请求列表。
感谢您关注我们的 2.3 版本发布,希望您喜欢使用 Deno 进行开发!
在 Twitter、Discord、BlueSky 和 Mastodon 上获取技术支持、分享您的项目或简单地打个招呼。