从使 fetch
和 WebStreams
稳定化到引入实验性的 WebSocket 客户端,Node.js 21 正在为服务器端 JavaScript 执行设定新的标准。
V8 11.8 的更新不仅提升了性能,还添加了开发者一直期待的新语言功能。
让我们来看看所有 Node.js 21 的功能!
稳定化的 fetch/WebStreams
所以,Node.js 21 决定稳定化 fetch/WebStreams,嗯?对于我们这些老手来说,“稳定”听起来就像是音乐,特别是在那些晚上调试代码的时候,把我们的头发搞得灰白之后。
稳定化的 fetch/WebStreams 概述
Node.js 中的 fetch 和 WebStreams 现在和你最喜爱的集成开发环境一样稳定,只要你禁用所有从未使用过的扩展功能。
// 在 Node.js 21 中使用 fetch
fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data));
这段代码是一个基本示例,但想象一下不需要引入外部库的情况。少了依赖地狱,更多了心安理得!
对开发实践的影响
随着 fetch/WebStreams 标志着“稳定”的旗帜,你的开发实践即将焕然一新。我们谈论的是更干净的代码,更少的“为什么这个不工作”的时刻,以及更流畅的数据处理体验。
还记得以前我们必须为与 fetch 相关的一切使用第三方包吗?啊,那些美好的旧时光……还是说吗?
内置 WebSocket 客户端
接下来是内置的 WebSocket 客户端。实验性的,他们说?嗯,每个 C# 开发者都知道,“实验性”只是“这将会是一个有趣的调试过程”的另一个说法。但别担心!
Node.js 21 带来了 WebSocket 的乐趣,无需使用自上次《权力的游戏》季节还好的包解决方案。
// 在 Node.js 21 中尝试使用 WebSockets
const webSocket = new WebSocket('ws://localhost:8080');
webSocket.onmessage = function(event) { console.log(`来自服务器的消息:${event.data}`);
};
这段代码展示了如何轻松连接到 WebSocket 服务器。这就像是打开了一条直接与服务器通信的线路,说:“嘿,让我们保持联系吧”,而不必为每一点数据都说 HTTP 的“请”和“谢谢”。
限制?
内置 WebSocket 客户端的实际应用范围与你安装并且已经忘记了的 npm 包的数量一样广泛。实时应用程序、聊天系统、实时更新 —— 都可以。限制呢?
嗯,它是实验性的,所以也许不要完全依赖它来确保整个应用程序的成功。把它想象成那个让你尝试新事物的一位冒险朋友;令人兴奋,但需要谨慎对待。
V8 11.8 更新
V8 引擎,即驱动 Node.js 的 JavaScript 核心,已经在 11.8 版本中得到了严重的调整。这次更新不仅仅是一些微调,而是像是从可靠的轿车升级到了跑车。主要功能?数组分组和 ArrayBuffer.prototype.transfer
。
首先是数组分组。这就像是终于有了一种内置方法来将你杂乱的数组元素组织成一个整洁的结构,而不用担心自己的头发会被搞乱。想象一下,你有一个水果数组,你想按类型对它们进行分组:
// 数组分组示例
let fruits = [ { name: "苹果", type: "树" }, { name: "橘子", type: "柑橘类" }, // 在这里想象更多的水果
];
let grouped = groupBy(fruits, fruit => fruit.type);
这个简单的代码片段会把你凌乱的水果数组变成一个井井有条的集合,在这里找到所有柑橘类或者树果就变得非常容易。
然后是 ArrayBuffer.prototype.transfer
。对于初学者来说,这可能听起来像是财务术语,但实际上,它对于处理二进制数据来说是一个改变游戏规则的功能。它允许你将 ArrayBuffer 的所有权转移到一个具有不同大小的新 ArrayBuffer 中,而无需逐字节复制数据。
这就像是能够搬进一个更大的房子,而不必一个字节一个字节地打包和解包所有东西。
Node.js 测试运行器中的通配符支持
还记得在 Node.js 中指定测试感觉像是闭着眼睛穿针引线的日子吗?好了,那些日子已经过去了。Node.js 测试运行器中的新通配符支持就像是为你的测试配备了 GPS。
它允许你使用通配符模式轻松地针对测试文件,这样你就可以用最少的麻烦运行一组特定的测试。
举例
假设你有一个庞大的测试套件
,其中包含数百个文件,分散在几十个目录中。你想运行所有与“用户”功能相关的测试,但害怕把它们都列出来。这就是通配符的用武之地:
node --test **/*user*.test.js
这个命令会神奇地挑选出所有文件名中带有“user”的测试文件,无论它们在项目结构中的哪个位置。这就像是有一根魔杖可以选择性地运行测试,使你的开发工作流程更高效,更少出错。
ESM: --experimental-default-type
标志
在不断发展的 JavaScript 世界中,Node.js 21 中引入的 --experimental-default-type
标志就像是在你的集成开发环境中发现一个改变一切的新快捷方式。对于那些经常在 ES 模块和 CommonJS 之间摇摆不定的人来说,这个标志是一个改变游戏规则的功能。
这里的情况是这样的:通过设置这个标志,你可以切换 Node.js 为你的项目使用的默认模块系统。这就像是告诉 Node,“嘿,我更喜欢 ES 模块而不是 CommonJS”,反之亦然,而不必重命名文件或在你的 package.json
中添加 "type": "module"
。
// 默认情况下将一个 .js 文件作为 ES 模块运行
node --experimental-default-type=module my-script.js
对项目配置的实际影响
实际影响相当显著。这就像是 Node.js 给我们提供了一个模块管理的瑞士军刀。下面是一些情景,这个标志是一个救命稻草:
- 迁移旧项目:轻松地将一个旧项目切换到使用 ES 模块,而不需要进行大规模改造。
- 混合模块类型:在具有 ES 和 CommonJS 模块混合的项目上工作,而不用不断担心兼容性问题。
- 简化配置:少了
package.json
的烦恼,使你的项目设置更清晰、更简单。
这个功能特别适用于那些喜欢尝试最新 JavaScript 特性但又害怕样板和设置复杂性的人。
模块自定义钩子的变化
还记得在 Node.js 中定制模块行为时感觉像是用勺子做心脏手术吗?好了,那些日子已经过去了。Node.js 21 引入了更清洁、更直观的方式来使用 globalPreload
转变为 register
和 initialize
钩子。
这种变化就像是从基于文本的冒险游戏升级到完整的角色扮演游戏。你有更多的控制、更好的工具,而且意外出错的机会更少了。
它是如何工作的?
在你现有的项目中实施这些变化听起来可能有些令人生畏,但实际上更像是学习一种新的编程语言,只是字母还是一样的。这里有一个快速指南,帮助你入门:
- 逐步淘汰
globalPreload
:找出你的项目中正在使用globalPreload
的地方。是时候告别它,并感谢它的服务了。 - 接受
register
和initialize
:这些新钩子是你的朋友。使用register
从应用程序线程发送数据到你的定制钩子。initialize
用于在线程之间建立通信通道。这就像是在你的模块之间建立秘密握手。
// 使用 register 和 initialize 钩子的示例
node --loader ./my-custom-loader.mjs my-app.js
这段代码片段代表了新的做事方式。用你的模块加载器脚本替换 ./my-custom-loader.mjs
,该脚本使用 register
和 initialize
钩子。
llhttp 9.1.2 严格模式强制执行
随着 Node.js 21 的发布,其中一个突出的改进是在 llhttp 9.1.2
中的严格模式强制执行。对于不了解的人来说,llhttp
是 Node.js 使用的底层 HTTP 解析库,它类似于 HTTP 世界的语法警察。转换到严格模式就像是从一个宽松的让一些错误滑过的老师变成了一个严格的让每个逗号和句号都在它应该的地方的教授。
那么,这对开发者为什么重要呢?本质上,这个改变旨在通过执行更严格的解析过程来增强安全性和可靠性。这就像是点缀你的 i 并且画上横线;它确保你的应用程序处理的 HTTP 请求和响应是应该的,从而减少与解析相关的安全漏洞的可能性。
适应严格模式
适应严格模式可能看起来令人生畏,就像是学习一种新的编程语言语法一样。但不用担心!这里有一些顺利过渡的技巧:
- 查阅
文档:首先要了解严格模式实施的具体细节。毕竟,知识就是力量。
- 测试你的应用程序:在测试环境中运行你的应用程序,并监视任何
llhttp
相关的错误。这就像是在大表演之前进行干冰试验。 - 更新你的代码:如果遇到问题,更新你的 HTTP 处理代码以符合严格模式的要求。这可能涉及调整你如何格式化标头或管理分块响应。
通过采取这些步骤,你可以确保你的应用程序在新的严格模式规定下保持健壮和安全。
全局 navigator
对象集成
如果你涉足过前端开发,你可能对 navigator
作为获取浏览器相关信息的工具很熟悉。将这个对象引入到 Node.js 中就像是拥有了一把瑞士军刀;它装满了有用的功能,但现在你可以在一个全新的环境中使用它。
特别值得注意的是 navigator.hardwareConcurrency
属性。它显示可用的逻辑处理器核心数量,使 Node.js 应用程序能够更加明智地分配资源和并行处理。
这就像是了解你的应用程序引擎下面的马力,使你能够更有效地优化性能。
示例
使用 navigator.hardwareConcurrency
可以显著影响你为性能设计 Node.js 应用程序的方式。这里有一个简单的示例:
console.log(`可用的逻辑 CPU 核心数量:${navigator.hardwareConcurrency}`);
这段代码片段可能是一个函数的第一步,根据可用的处理能力动态调整其操作。例如,你可以使用这些信息来确定要生成多少个子进程,或者并行运行多少个任务。
使用 navigator.hardwareConcurrency
的最佳实践包括:
- 动态调整:使用核心数量动态调整应用程序的工作负载。更多的内核可能意味着你可以并行做更多的事情,但请记住,更多并不总是更好。关键在于找到合适的平衡。
- 备用方案:Node.js 运行的环境不一定支持
navigator
对象的每个特性。始终包含备用逻辑来优雅地处理这些情况。
总结思考
总的来说,这个版本不仅完善了核心功能,还引入了前瞻性的能力,以应对现代 Web 开发的需求。
随着我们将这些更新整合到我们的工作中,创新和提升我们的应用程序的潜力是巨大的。
Node.js 21 不仅仅是一个更新;它是一个充满活力和不断发展的生态系统的证明,它不断推动着 Web 技术可能性的边界。