跳到主要内容
Deno 2.4 已发布,带来 deno bundle、字节/文本导入、OTel 稳定版等新特性
了解更多
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/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 将使用 `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 规范最近更新,在 `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。在此处阅读更多内容