跳至主要内容
Deno 2 终于来了 🎉️
了解更多
Deno 1.44

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 注册表

许多大型组织都托管他们自己的私有 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/[email protected]"
  }
}
// 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(),以使其能够干净地关闭工作线程。
  • 修复将 MessagePort 传递给 Node worker_threads 时缺少的方法。这解决了与 vitest 中工作线程通信相关的几个错误。
  • 允许 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 的罕见重新导出错误。
  • 修复 napi_get_elementnapi_set_element,使 npm DuckDB 适配器能够与 Deno 一起使用。
  • 使 HOME 目录检测更可靠,以便在 OpenNext 中运行服务器函数。

此外,deno task 在处理 package.json 文件时变得更加智能。如果发现任务调用 npm run <another_task>,Deno 将使用 deno task 而不是运行 npm 二进制文件,有关更多详细信息,请参见#23036

性能改进

Deno 1.44 引入了一些性能改进,使 Deno 运行速度更快,内存效率更高。我们预计许多项目将看到内存使用量减少 5-30%,具体取决于工作负载。

  • 使用 V8 指针压缩减少内存使用量:重新启用 V8 指针压缩使 V8 能够更有效地存储指针,从而大大减少内存使用量。这种改进对于具有大量对象分配的实际场景特别有益,导致内存消耗显着减少。 比较 http hello world、文本编码和渲染 deno.com 的内存消耗的基准测试结果。对于合成基准测试,内存减少了 2-7%,但对于 deno.com 这样的实际场景,大约减少了 30%

  • 更快的模块加载:通过并行执行任务来优化模块加载,包括分析和发出 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 规范 最近更新了 RequestResponse 类上的新 .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

通常定义接受 boolean 作为参数的函数。 但是,将 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 中,我们进行了一些更改以改进此功能。

我们更新了从本机代码处理 u64i64 类型的方式。 以前,这些符号表示为 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 https://127.0.0.1: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 ✨、chrisz、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 进行构建!

🍋 新鲜的 2.0 版本即将到来。

我们的下一个主要 Fresh 版本将更加简单,并拥有更具可组合性的路由 API。 在此处阅读更多信息.