Deno 1.44:私有 npm 注册表、改进的 Node.js 兼容性和性能提升
Deno 1.44 引入了对私有 npm 注册表的支持,用户可以通过配置 `.npmrc` 文件来在 Deno 中使用内部包。此外,Deno 1.44 现在支持 gRPC 连接,从而能够与 Google Cloud Platform 等服务进行稳定且高性能的通信。此版本还改进了 Node.js 兼容性,并重新启用了 V8 指针压缩以显著提升性能。与往常一样,此版本中还包含许多其他功能和改进,以使您的开发体验更加流畅。
要升级到 Deno 1.44,请在终端中运行以下命令
deno upgrade
如果 Deno 尚未安装,请运行以下命令之一进行安装,或在此处了解如何安装。
# Using Homebrew (macOS):
brew install 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 1.44 中的新特性
- 支持私有 npm 注册表
- 现在支持 gRPC 连接
- Node.js 兼容性改进
- 性能改进
- 标准库正趋于稳定
Deno.exitCode
APIRequest.bytes()
和Response.bytes()
- Lint 规则更新
- 测试运行前清空覆盖率目录
- 打印慢速测试反馈
Deno.FsFile
稳定性改进- FFI API 变更
- 在
deno serve
中选择一个随机端口 WebSocket
超时- 语言服务器改进
- 使用
DENO_FUTURE=1
尝试 Deno 2 功能 - 致谢
支持私有 npm 注册表
许多大型组织都托管自己的私有 npm 注册表来管理内部包。Deno 1.44 现在支持使用 `.npmrc` 文件来配置 Deno 从此私有注册表获取包。此功能在 `package.json` 中使用私有包或直接使用 `npm:` 标识符导入包时可用。
// .npmrc
@mycompany:registry=http://mycompany.com:8111/
//mycompany.com:8111/:_auth=secretToken
// deno.json
{
"imports": {
"@mycompany/package": "npm:@mycompany/package@1.0.0"
}
}
// main.ts
import { hello } from "@mycompany/package";
console.log(hello());
$ deno run main.ts
Hello world!
您也可以在 `package.json` 文件中使用私有 npm 包
// package.json
{
"dependencies": {
"@mycompany/package": "1.0.0"
}
}
// main.ts
import { hello } from "@mycompany/package";
console.log(hello());
$ deno run main.ts
Hello world!
现在支持 gRPC 连接
Deno 现在可以使用 npm 中的 `@grpc/grpc-js` 客户端库连接到 gRPC 服务。这使您能够从 Deno 连接到 gRPC 服务,例如 Google Cloud Platform。这是一个使用 Google Cloud SDK 通过 Google Cloud Vision API 对图像进行分类的示例
import { ImageAnnotatorClient } from "npm:@google-cloud/vision";
const client = new ImageAnnotatorClient();
const [result] = await client.labelDetection("./cat_dog.webp");
const labels = result.labelAnnotations;
console.log("Labels:");
for (const label of labels) {
console.log(" - ", label.description);
}
gRPC 是一种高性能、开源、通用的 RPC 框架,可实现服务之间的有效通信。借助 gRPC 支持,您可以构建利用 gRPC 低延迟通信能力的实时交互式应用程序。
Node.js 兼容性改进
此版本标志着 Deno 在与 Node.js 和 npm 包兼容性方面迈出了重要一步。
作为一个重要的里程碑,我们已能够在此版本中使用 Deno 运行 Next.js 应用程序。虽然仍有一些粗糙之处,例如需要使用 `DENO_FUTURE=1`,但我们相信可以快速解决这些问题。我们很快将发布一篇博客文章,详细介绍如何使用 Deno 运行 Next.js 应用程序。
目前,这里有一个使用 Deno 运行 Next.js 应用程序的示例,其中使用了新的 Next.js 服务器操作来流式传输文件
其他 Node.js 兼容性改进包括
- 添加 `Buffer.isUtf8()` 和 `Buffer.isAscii()`,`ts-node` 依赖于它们。
- 修复 npm 依赖项打包并传递 `process.uptime` 时发生的错误。此错误发生是因为我们的实现依赖于 `this` 的正确性。我们已重写 `process.uptime`,使其不再依赖任何 `this` 引用。
- 修复 `SIG*` 监听器未在 `process.listeners` 中被跟踪的问题。这修复了 `signal-exit` 包无法正确退出的错误。此包在许多流行的 CLI 工具(例如 `vitest`)中使用。
- 修复 `tinypool` 无法终止 `worker_threads` 的问题。这是由于我们在 `Worker.terminate()` 中返回了不同的返回码造成的。`tinypool` 包在 `vitest` 中被大量使用。
- 为 `tinypool` 提供了 `AsyncResource.emitDestroy()` 存根,使其能够干净地关闭 workers。
- 修复将 `MessagePort` 传递给 Node `worker_threads` 时缺少方法的问题。这解决了 `vitest` 中与 worker 通信相关的几个错误。
- 允许 `Process` 类在不使用 `new` 关键字的情况下实例化。这解决了流行测试运行器 `jest` 的一个问题。
- 提供了 `perf_hooks.PerformaceObserver` 存根,以使 Next.js 的 `build` 命令正常工作。
- 在尝试关闭资源之前检查资源是否存在。这使得 GRPC 的截止日期示例能够工作。
- 为具有 bin 入口点的包设置 `node_modules/.bin` 条目。这是 npm 支持方面长期以来一直要求的功能。
- 使解析不正确的 `package.json` 文件更加健壮。一些 npm 包附带的 `package.json` 文件不符合预期的数据类型。
- 修复在目录而不是文件上调用 `fs.rmSync` 时抛出错误异常的问题。
- 为 `ava` 提供 `findSourceMap` 存根
- 修复 `ServerResponse` 上默认状态码属性未初始化为 `200` 的问题。这使得 `11ty` 开发服务器能够工作。
- 修复 `node:process` 中缺少 `geteuid` 的问题。
- 修复 gRPC 中流未被标记为已取消的问题。这使得流式传输示例能够工作。
- 修复在发出 `response` 事件时发出的错误标志。这修复了 gRPC 中的错误传播。
- 允许通过 `delete` 关键字删除 `process.env` 值。此模式有时用于集成测试。
- 为每个 `worker_thread` 使用单独的模块缓存。解决此问题后,`SvelteKit` 即可正常工作。
- 修复在 `@solana/spl-governance` npm 包中发现的 CommonJS 罕见的 re-export 错误。
- 修复 `napi_get_element` 和 `napi_set_element`,这使得 npm DuckDB 适配器能够与 Deno 配合使用。
- 使 OpenNext 中运行服务器功能的 HOME 目录检测更加可靠。
此外,`deno task` 在处理 `package.json` 文件时变得更智能。如果发现某个任务调用了 `npm run
性能改进
Deno 1.44 引入了多项性能改进,使 Deno 更快、内存效率更高。我们预计许多项目将看到内存使用量减少 5-30%,具体取决于工作负载。
通过 V8 指针压缩减少内存使用:重新启用 V8 指针压缩功能,使 V8 能够更高效地存储指针,大大减少内存使用。此增强功能对于存在大量对象分配的实际场景特别有利,可显著降低内存消耗。
更快的模块加载:通过并行执行任务来优化模块加载,包括分析和发出 CommonJS 导出和重新导出、在 `deno cache` 操作期间将 TypeScript 编译为 JavaScript、在模块解析期间跳过不必要的目录查找,以及尽快下载元数据文件。这些增强功能显著加快了模块处理和缓存效率,减少了整体启动时间。这些更改使大量使用动态导入的项目启动速度提高约 2-3 倍(#23856、#23894、#23892、#23851、#23836)。
在 AWS Lambda 中启动时间更快:在 `DENO_DIR` 中为 SQLite 数据库使用预写日志(WAL)日志,可改善 Deno 实例的代码缓存和启动时间,这在 AWS Lambda 等无服务器环境中尤其有利。此更改有助于减少冷启动延迟,使无服务器应用程序响应更迅速(#23955)。
改进语言服务器性能:在 LSP 中缓存打开文档的语义令牌,可增强语言服务器性能,通过减少重新分析打开文件所需的时间,使开发更流畅、更高效(#23799)。
标准库正趋于稳定
Deno 标准库提供了一组高质量的包,它们经过核心团队审核并保证与 Deno 兼容。
目前,标准库将专门发布到 JSR 的 `@std` 作用域下。标准库的现有版本将继续保留在 https://deno.land/std。这一举措,以及 Deno 新的工作区功能,都是 Deno 2 即将推出的变更的一部分。欲了解更多详情,请查看标准库的稳定化路线图。
Deno.exitCode
API
此版本新增了一个稳定的 `Deno.exitCode` API。您可以使用此 API 来获取和设置程序可能返回的退出代码
console.log("Initial code", Deno.exitCode);
try {
console.log("Try to retrieve data...");
await fetch("https://doesnt.exist");
} catch (e) {
console.log("Failed to retrieve data");
// Set the exit code, to a special value to signal a failure.
Deno.exitCode = 42;
// Perform some additional cleanup...
}
console.log("Exit code after the task", Deno.exitCode);
$ deno run --allow-net exit_code.ts
Initial code 0
Try to retrieve data...
Failed to retrieve data!
Exit code after the task 42
$ echo $?
42
您可以使用此 API 分配特定的退出代码,但不会立即退出,例如使用 `Deno.exit(code?)` API 时。此 API 允许在程序结束前执行额外的清理工作。
此 API 与 Node.js 的 `process.exitCode` API 非常相似,但 `Deno.exitCode` 具有更强的验证功能,并要求设置一个有效的十进制退出代码。两个 API 协同工作并按预期反映值。
import process from "node:process";
console.log("Deno 1 - exit code -", Deno.exitCode);
console.log("Node.js 1 - exit code -", process.exitCode);
Deno.exitCode = 42;
console.log("Deno 2 - exit code -", Deno.exitCode);
console.log("Node.js 2 - exit code -", process.exitCode);
process.exitCode = 70;
console.log("Deno 3 - exit code -", Deno.exitCode);
console.log("Node.js 3 - exit code -", process.exitCode);
$ deno run exit_code.ts
Deno 1 - exit code - 0
Node.js 1 - exit code - 0
Deno 2 - exit code - 42
Node.js 2- exit code - 42
Deno 3 - exit code - 70
Node.js 3 - exit code - 70
$ echo $?
70
感谢 Luke Edwards 对此 API 的建议和初步实现。
Request#bytes()
和 Response#bytes()
Fetch API 规范最近更新,在 `Request` 和 `Response` 类上新增了 `.bytes()` 方法。这个小小的改动显著改善了处理字节时的开发体验。您不再需要获取底层的 `ArrayBuffer` 并将其转换为 `Uint8Array`。
// Before:
const response = await fetch("https://example.com");
const buffer = new Uint8Array(await response.arrayBuffer());
// After
const response = await fetch("https://example.com");
const buffer = await response.bytes();
Lint 规则更新
此版本为现有规则带来了重大更新,并新增了一条 lint 规则。
no-undefined-vars
no-undefined-vars
现在支持 JSX 和 TSX 文件。
import React from "react"; // This import is now flagged as unused!
const Foo = () => {
return "Hello world!";
};
此改进对 Fresh 用户特别有用。
此规则仍像以前的版本一样默认启用。
no-boolean-literal-for-arguments
定义接受 `booleans` 作为参数的函数很常见。然而,将 `boolean` 字面量作为参数传递可能会导致函数内部参数作用的上下文不足。
function redraw(allViews: boolean, inline: boolean) {
// redraw logic...
}
redraw(true, true);
此规则强制所有布尔参数都需要使用“自解释”常量。
function redraw(allViews: boolean, inline: boolean) {
// redraw logic...
}
const ALL_VIEWS = true;
const INLINE = false;
redraw(ALL_VIEWS, INLINE);
感谢 Jorge Martin Juarez 实现了此规则。
此规则默认禁用。您可以在 `deno.json(c)` 配置文件中如下启用它
{
"lint": {
"rules": {
"include": ["no-boolean-literal-for-arguments"]
}
}
}
测试运行前清空覆盖率目录
Deno 内置的测试运行器新增了一个 `--clean` 标志,该标志将在运行测试套件之前清空覆盖率目录。这看似是一个小改动,但它解决了已删除文件的覆盖率数据仍然存在的问题。
deno test --coverage --clean
请注意,此标志在并行或串行运行多个 `deno test` 命令,然后查看聚合覆盖率报告时会导致冲突。如果您并行运行测试,则不应使用 `--clean` 标志。如果串行运行,则仅将 `--clean` 标志传递给第一次 `deno test` 调用。
打印慢速测试反馈
我们注意到长时间运行的测试可能会导致混淆,因为在没有输出显示时,不确定测试运行器是否仍在工作。
$ deno test slow_test.ts
Check file:///tmp/test_slow.ts
running 1 test from test_slow.ts
test ...
'test' has been running for over 1m0s
'test' has been running for over 2m0s
ok (2m10s)
ok | 1 passed | 0 failed (2m10s)
您可以使用 `DENO_SLOW_TEST_TIMEOUT` 环境变量配置这些消息的间隔,该变量接受在多少秒后打印消息的数字。我们正在考虑为慢速测试添加一个硬超时,这将强制中止测试。我们很乐意听取您对此功能的反馈。
Deno.FsFile
稳定性改进
您不再需要使用 `--unstable-fs` 标志,该标志在各种上下文中(包括与 Next.js 等框架一起使用时)经常导致问题。以下方法已稳定化:
Deno.FsFile.syncData[Sync]()
和Deno.FsFile.sync[Sync]()
(#23733)Deno.FsFile.unlock[Sync]()
和Deno.FsFile.lock[Sync]()
(#23754)
这些稳定性改进消除了对不稳定标志的需求,使文件系统操作更流畅、更可靠。通过整合这些更改,API 现在直接在稳定的 Deno 运行时中支持基本的文件同步和锁定功能。此增强功能对于确保数据完整性和有效处理并发文件操作特别有用。
FFI API 中的更改
Deno 的 FFI API 允许您从 JavaScript 代码调用原生库。在 Deno 1.44 中,我们对该功能进行了一些改进。
我们更新了对原生代码中 `u64` 和 `i64` 类型的处理。以前,这些符号表示为 `number | bigint`。从 v1.44 开始,它们始终为 `bigint` 类型。此更改使 API 与 JavaScript 对大整数的处理保持一致,并确保更好的性能和类型一致性。虽然这是一个破坏性更改,但 API 仍不稳定,我们正在利用此机会解决类型怪癖,以使 `Deno.dlopen()` API 趋于稳定。(#23981,#23983)
这些更新是我们持续努力稳定 Deno 2 的 FFI API 的一部分,旨在确保它为从 Deno 调用原生库提供健壮且一致的体验。
deno serve
中选择一个随机端口
在 `deno serve` 命令添加到 Deno 已有一个月了。它允许您以声明式方式编写服务器。我们注意到在开发过程中,您通常希望服务器启动,但并不关心它将在哪个端口上生成。因此,我们添加了对传递 `--port 0` 的支持,它将返回由您的操作系统选择的随机空闲端口。
$ deno serve --port 0 server.ts
deno serve: Listening on http://localhost:58333/
WebSocket
超时
Deno 的 `WebSocket` API 有一个 `ping/pong` 机制来保持连接活跃。不幸的是,默认的 120 秒超时时间对于许多流行的反向代理服务器(如 Nginx)来说太长了。其中许多服务器的默认超时时间为 60 秒。这导致连接到 Deno WebSocket 服务器的连接过早关闭。
`ping/pong` 消息的默认“空闲”超时时间已降低到 30 秒。通过此更改,大多数 WebSocket 服务器应更可靠,无需任何手动干预。
感谢 Alex Gleason 实现了此更改。
语言服务器改进
本月我们花费了大量时间清理语言服务器,从而带来了多项性能改进和错误修复,具体包括:
- 为打开的文档添加了语义令牌缓存 (#23799)
- 重用“sloppy imports”解析器 (#23764)
- 将导入修复应用于缺少声明的代码操作 (#23924)
- 修复命名示例中的 JSDoc 显示问题 (#23927)
- 显示方法的引用 CodeLens (#23804)
DENO_FUTURE=1
尝试 Deno 2 功能
使用 我们将继续发布将在 Deno 2 中生效的更改,您今天可以通过使用 `DENO_FUTURE=1` 环境变量运行 Deno 来尝试这些更改。
此版本带来以下更改:
deno install
现在可以处理将依赖项添加到 `deno.json(c)` 和 `package.json` 文件中,从而大大简化了 Node.js 项目的迁移。- 所有文件系统 API 都已稳定(不再需要 `--unstable-fs` 标志)
- WebGPU API 已稳定(不再需要 `--unstable-webgpu` 标志)
- FFI API 已稳定(不再需要 `--unstable-ffi` 标志)
deno install
为具有二进制入口点的 `npm` 包正确设置 `node_modules/.bin/` 条目
致谢
没有社区的帮助,我们无法构建 Deno!无论是通过在我们的社区 Discord 服务器中回答问题,还是报告错误,我们都非常感谢您的支持。特别是,我们要感谢以下人员对 Deno 1.44 的贡献:Alex Gleason、Antoine du Hamel、Bedis Nbiba、charlotte ✨、chirsz、Evan、Felipe Baltor、futsuuu、Hajime-san、Hasan-Alrimawi、Kenta Moriuchi、Kyle Kelley、Luke Edwards、Mathias Lafeldt、Mattias Buelens、Mike Mulchrone、Milly、Simon Lecoq、Volker Schlecht。
您想加入 Deno 贡献者的行列吗?请在此处查看我们的贡献文档,我们期待下次在名单上看到您。
信不信由你,上面列出的更改仍然没有告诉您 1.44 中所有改进的内容。您可以在 GitHub 上查看 Deno 1.44 中合并的完整拉取请求列表。
感谢您关注我们的 1.44 版本发布,希望您喜欢使用 Deno 进行开发!
🍋 Fresh 2.0 即将到来。
我们的下一个主要 Fresh 版本将更简单,并提供更具组合性的路由 API。在此处阅读更多内容。