Node.js 21正式发布

我们很高兴地宣布Node.js 21版本已经发布!主要亮点包括将V8 JavaScript引擎升级到11.8版本、稳定的fetch和WebStreams、一个用于切换模块默认设置的新实验性标志(–experimental-default-type)、内建的WebSocket客户端、我们的测试运行器的多个更新等等!

当Node.js 20版本进入长期支持(LTS)阶段后,Node.js 21将取代Node.js 20成为我们的当前版本。根据发布计划,Node.js 21将成为“当前”版本,持续6个月,直到2024年4月。

该项目在许多领域取得了进展,许多新功能和修复已经流入现有的LTS版本。因此,Node.js 21版本的变更概述只代表了自上一个主要版本发布以来的一小部分工作和特性。本文将针对这些变更为大家提供更多背景信息。

您可以在https://github.com/nodejs/release了解更多有关我们的发布政策。

要下载Node.js 21.0.0版本,请访问:https://nodejs.org/en/download/current/。您可以在https://nodejs.org/en/blog/release/v21.0.0找到发布帖子,其中包含了此版本中包含的所有提交的完整列表。

重要变更

稳定的fetch/WebStreams

最近的Node.js更新,版本21,包括对fetch模块和WebStreams的重要更改。在最近的更新后,这两个模块都被标记为稳定。

这影响了WebStreamsFormDataHeadersRequestResponse和fetch。

内建的WebSocket客户端

这个版本引入了一个实验性的、与浏览器兼容的WebSocket实现。可以通过标志–experimental-websocket来启用它。作为任何实验性功能,它可能会发生变化。

V8 11.8

像往常一样,Node.js中包括了V8引擎的新版本(升级到Chromium 118的一部分,版本为11.8),带来了性能改进和新的语言特性,包括:

  • 数组分组
  • ArrayBuffer.prototype.transfer
  • WebAssembly扩展-const表达式
Node.js测试运行器中支持通配符

随着最新的Node.js更新,测试运行器在指定–test参数时引入了对通配符表达式的支持。这意味着你现在可以使用强大的通配符模式更高效和灵活地运行测试。例如,你可以使用类似node –test **/*.test.js的命令在多个目录中执行所有带有.test.js扩展名的文件的测试。

ESM:--experimental-default-type标志来切换模块默认值

新标志--experimental-default-type可用于切换Node.js使用的默认模块系统。已经明确定义为ES模块或CommonJS的输入,例如通过package.json的“type”字段或.mjs/.cjs文件扩展名或–input-type标志,不受影响。当前暗示为CommonJS的内容将在--experimental-default-type=module下解释为ES模块:

  • 如果未指定--input-type,通过--evalSTDIN提供的字符串输入。
  • 以.js或无扩展名结尾的文件,如果同一文件夹或任何父文件夹中没有package.json文件。
  • 以.js或无扩展名结尾的文件,如果最近的父package.json字段缺少type字段,除非该文件夹位于node_modules文件夹中。
    此外,如果传递了--experimental-wasm-modules并且文件以WebAssembly前言\0asm开头,则无扩展名的文件将被解释为WebAssembly。

我们还在探讨使用ES模块语法检测作为Node.js知道何时将文件解释为ES模块的一种方法。我们的目标是最终找到一种在默认情况下支持ES模块语法的方法,而只产生最小的破坏性变化。

模块自定义挂钩globalPreload已移除;改为使用registerinitialize

模块自定义挂钩globalPreload已被移除。取而代之,使用register从应用程序线程发送数据到自定义挂钩,使用initialize来建立线程之间的通信通道。

为fs.writeFile函数添加flush选项

在写入文件时,数据可能不会立即刷新到永久存储。这允许后续的读操作看到陈旧的数据。此PR向fs.writeFile函数系列添加了一个“flush”选项,它在成功写操作结束时强制刷新数据。

性能

性能是运行时的一个重要属性,我们的@nodejs/performance团队在过去的一年里一直在努力改进URL、fetch、streams、node:fs和HTTP。

streams

Node.js流团队继续优化可写和可读流。在这个版本中,流维护者Robert Nagy带领团队通过删除多余的检查、利用位图和以更高效的方式调度回调来进一步优化流。

HTTP

以前,在写入分块响应时,Node.js将创建一个单独的块,无论响应是否被阻止。这会导致客户端和服务器端都产生不必要的开销。

这个变化通过在解锁响应时为所有write(…)调用创建一个单一块来解决了这个问题。

考虑以下基于Transfer-Encoding文档的示例:

1
2
3
4
res.cork();
res.write('Mozilla');
res.write(' Developer Network');
res.uncork();

在每个块的开头,您需要添加当前块的长度的十六进制格式,后跟’\r\n’,然后是块本身

,后跟另一个’\r\n’。终结块是一个常规块,唯一的例外是它的长度为零。

导致响应流:

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
7\r\n
Mozilla\r\n
18\r\n
Developer Network\r\n
0\r\n
\r\n

在这个PR中,在解锁响应时,所有东西都被合并到一个单一的块中,绕过了很多不必要的开销。

1
2
3
4
5
6
7
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25\r\n
Mozilla Developer Network\r\n
0\r\n
\r\n
llhttp 9.1.2严格模式强制执行

在之前的Node.js版本中,默认情况下未启用严格模式。随着最新更新,以前包含在严格模式中的所有设置现在都已默认启用,增强了代码的可靠性和安全性。
在头部之后,现在强制存在\r\n(先前仅允许\r)。此外,在解析具有Connection: close标头的消息后,不再允许数据传输。此更改增强了协议的遵循性并改进了连接处理。
为了适应特定用例,现在存在–insecure-http-parser标志。此选项允许用户禁用上述更改,并保持与先前解析行为的向后兼容性。

这些更新旨在增强整个系统的稳定性,并改善Node.js应用程序中数据处理的一致性。鼓励开发者审查他们的代码库,并相应调整他们的实现,以确保与最新版本的无缝集成。

在Node.js 21中,我们引入了全局navigator对象,增强了Web互操作性。现在,开发者可以通过navigator.hardwareConcurrency访问硬件并发信息

废弃功能

[4b08c4c047] - (SEMVER-MAJOR) lib: 在运行时废弃punycode(Yagiz Nizipli)#47202
[ccca547e28] - (SEMVER-MAJOR) util: 在运行时废弃返回Promise的函数(Antoine du Hamel)#49609

行动起来!

尝试使用新的Node.js 21版本!我们很乐意听到您的反馈。使用Node.js 21测试您的应用程序和模块有助于确保您的项目与最新的Node.js变化和功能的未来兼容性。

还值得注意的是,Node.js 16(LTS)已经结束生命周期,因此我们强烈建议您开始计划升级到Node.js 18(LTS)或Node.js 20(LTS)。