
Node.js 21 发布详解fetch 与 WebStreams 稳定、内置 WebSocket 客户端及性能优化全解析【免费下载链接】nodejs.orgThe Node.js® Website项目地址: https://gitcode.com/GitHub_Trending/no/nodejs.orgNode.js 21 是于 2023 年 10 月 17 日发布的 Current 版本本次发布将 V8 引擎升级到 11.8带来了稳定化的fetch与WebStreams、实验性内置 WebSocket 客户端、可切换模块默认类型的--experimental-default-type标志、测试运行器对 glob 表达式的支持以及 streams/HTTP 等关键路径上的性能优化。本文以 v21 发布公告 为主体结合 nodejs.org 网站仓库中与发布数据、下载与发布帖生成相关的源码实现逐项解读这些新特性及其背后的实现与使用方式。版本路线从 Current 到 LTS 的 6 个月周期Node.js 21 发布时处于 Current 状态它将取代当时的 Node.js 20 成为新的 Current 版本线。按照官方发布节奏Node.js 20 于当月晚些时候进入长期支持LTS而 Node.js 21 则以 Current 状态运行 6 个月直到 2024 年 4 月。在 nodejs.org 仓库中这种版本状态的判定逻辑被固化在发布数据生成器中。releaseData.mjs 中的getNodeReleaseStatus函数按以下优先级决定每个大版本的状态若已到达 EOL 日期support.phases.dates.end状态为EOL若最新版本处于 LTSlatest.lts.isLts为真状态为LTS否则状态为Current。const getNodeReleaseStatus (latest, eol) { const now new Date(); if (eol now new Date(eol)) { return EOL; } if (latest.lts.isLts) { return LTS; } return Current; };这段源码清晰地体现了 Node.js 版本线的三种状态划分也解释了发布公告中Node.js 21 将在未来 6 个月保持 Current这一表述的技术依据。这些数据最终被下载页、版本选择器Release.VersionDropdown以及各个表格组件消费用于在网站上动态展示当前版本状态。fetch 与 WebStreams 标记为稳定Node.js 21 的一个重要变化是将fetch模块以及WebStreams从实验性状态提升为稳定。这意味着WebStreams、FormData、Headers、Request、Response和fetch这组 Web 标准 API 在 Node.js 中不再是实验性功能可以直接在生产环境中依赖它们而不必担心 API 变更。这一变化的直接体现是你不再需要任何实验性标志就可以在服务端代码中像浏览器一样使用fetch发起 HTTP 请求、处理FormData表单数据或借助WebStreams以流式方式读写数据。对于在 Node.js 中编写 HTTP 客户端、下载代理或数据管道类应用而言这大幅降低了对外部依赖的需求。值得注意的是Node.js 的fetch实现基于 undici 库。在随后的 v21.0.0 详细发布帖 v21.0.0.md 中可以看到 undici 被更新到 5.25.4为fetch的稳定性提供了底层支撑。实验性内置 WebSocket 客户端Node.js 21 引入了一个浏览器兼容的WebSocket实现但该功能仍处于实验阶段需要通过标志启用node --experimental-websocket app.js启用后你可以在 Node.js 中直接使用标准 WebSocket API 建立与服务器之间的双向通信连接而无需安装第三方库。作为实验性功能其 API 在未来版本中仍可能发生变化因此生产环境使用前需要关注后续版本的变更公告。V8 11.8性能与新语言特性Node.js 21 内置的 V8 引擎升级到了 11.8对应 Chromium 118带来了性能提升和以下新语言特性Array groupingObject.groupBy/Map.groupBy允许按回调返回的键对数组元素进行分组ArrayBuffer.prototype.transfer支持将ArrayBuffer的所有权转移给新对象避免数据拷贝是结构化克隆与共享内存场景下的重要能力WebAssembly extended-const 表达式允许在常量表达式中执行更复杂的操作如全局变量读取、算术运算为 WebAssembly 编译器生成更灵活的常量提供了支持。V8 引擎的升级同时带来了模块 ABI 版本的变化NODE_MODULE_VERSION提升到 120这意味着针对旧版本 Node.js 编译的原生模块N-API 以外的直接绑定 V8 API 的 addon需要重新编译才能用于 Node.js 21。测试运行器glob 表达式支持Node.js 内置测试运行器test runner在本次更新中引入了对 glob 表达式的支持。此前通过--test参数指定测试文件时能力有限现在你可以使用强大的 glob 模式灵活地选择测试文件集合。例如跨多个目录运行所有.test.js后缀的测试文件node --test **/*.test.js这种模式让 CI 配置和本地测试执行更加灵活可以按目录、按命名模式或按扩展名精细控制哪些文件参与测试。发布公告中这一特性由 #47653 引入同批提交还包含了fs.globSync实现为文件系统级的 glob 匹配提供了原生支持。nodejs.org 仓库自身也大量使用 Node.js 测试生态例如 releaseData.test.mjs、vulnerabilities.test.mjs 等测试文件覆盖了发布数据与漏洞数据的生成逻辑展示了测试运行器在真实项目中的典型用法。ESM 模块默认类型切换--experimental-default-typeNode.js 21 新增了实验性标志--experimental-default-type用于翻转 Node.js 对模糊代码ambiguous code的默认模块解释方式。所谓模糊代码是指那些既没有被package.json的type字段显式声明、也没有通过.mjs/.cjs扩展名或--input-type标志明确类型的输入。这些输入默认按 CommonJS 处理。当传入--experimental-default-typemodule时以下三类输入会被改按 ES modules 解释通过--eval或 STDIN 提供的字符串输入当--input-type未指定时以.js结尾或没有扩展名的文件——前提是同一目录或任何父目录中不存在package.json以.js结尾或没有扩展名的文件——当最近的父级package.json缺少type字段时但node_modules目录内的文件除外。此外还有一个交互细节如果同时传入--experimental-wasm-modules且无扩展名文件以 WebAssembly 魔数\0asm开头则该文件会被解释为 WebAssembly 模块。发布公告同时提到Node.js 团队还在探索基于 ES 模块语法检测来自动判断文件模块类型的方式目标是最终能以最小的破坏性变更让 ES 模块语法默认可用。对于正在迁移到 ESM 的项目这个标志提供了在不动package.json的情况下先行验证默认 ESM行为的手段但需要注意它仍是实验性的。模块自定义钩子globalPreload移除改用register与initializeNode.js 21 移除了模块自定义钩子module customization hooks中的globalPreload。旧机制通过globalPreload在钩子线程与应用线程之间传递数据新方案将其职责拆分为两个部分register用于从应用线程向自定义钩子发送数据initialize用于在线程之间建立通信通道。这一改动是为了让模块自定义钩子的线程模型更清晰、更安全。使用自定义加载器loader的项目需要从旧的globalPreload写法迁移到新的registerinitialize组合。fs.writeFile 新增flush选项文件写入时数据并不总是立即刷入持久化存储后续读操作可能因此读到旧数据stale data。Node.js 21 为fs.writeFile系列函数fs.writeFile、fs.writeFileSync、fs.promises.writeFile新增了flush选项在成功写入结束后强制将数据刷新到永久存储import { writeFileSync } from node:fs; writeFileSync(data.txt, hello, { flush: true });这对于日志系统、数据库快照、崩溃恢复等对数据持久性有强要求的场景非常实用可以避免写入成功但断电后数据丢失的隐患。性能优化Streams 与 HTTP chunked 响应性能团队在 URL、fetch、streams、node:fs 和 HTTP 等模块上做了持续优化本次版本中有两个代表性改进。Streams 优化streams 维护者通过以下手段进一步优化了 Writable 和 Readable 流的性能移除冗余检查利用位图bitmap替代部分状态标志以更高效的方式调度回调。这些改动减少了每次数据块处理时的开销对高频读写场景有明显收益。HTTP 分块响应的合并在此之前对 chunked 响应调用多次.write(...)时Node.js 会为每次调用生成独立的分块无论响应是否处于 corked 状态这给客户端和服务端都带来了不必要的开销。以 Transfer-Encoding 分块编码 文档中的经典示例为例res.cork(); res.write(Mozilla); res.write( Developer Network); res.uncork();按照分块编码协议每个块需要以十六进制长度开头、跟随\r\n、再跟随块内容与\r\n终止块是长度为 0 的普通块。旧行为会生成两个数据块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本次优化后在uncork()时所有write(...)调用被合并为单个数据块绕开了大量不必要的开销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在 v21.0.0.md 的提交列表中该改动标记为(SEMVER-MAJOR)级别的 http 变更意味着依赖每次 write 生成独立 chunk这一旧行为的代码需要留意行为差异。这一优化也是本次版本中对外可见的性能收益之一。llhttp 9.1.2HTTP 解析严格模式全面开启Node.js 21 将 llhttp 升级到 9.1.2并默认启用此前仅在严格模式下生效的解析规则提升代码可靠性与安全性。主要变化包括此前未默认启用的严格模式设置现在全部默认开启header 之后必须存在\r\n此前允许单独的\rchunk 之后同样必须跟\r\n保证数据处理的一致性解析到携带Connection: close头的消息后不再允许继续传输数据以增强协议遵守度与连接处理能力。如果某些特殊场景需要兼容旧的解析行为可以通过--insecure-http-parser标志关闭上述变更。发布公告建议开发者审查自己的代码库并相应调整实现确保与新版解析器无缝集成。navigator 全局对象Node.js 21 引入了全局navigator对象增强与 Web 平台的互操作性。目前开发者可以通过它访问硬件并发信息console.log(navigator.hardwareConcurrency);该属性返回可用于并行任务的逻辑处理器核心数可用于动态调整 Worker 线程池大小、并发任务数等场景是实现按机器能力自适应并发的便捷手段。作为全局对象它无需require或import即可直接使用。弃用与破坏性变更本次发布包含两项运行时弃用runtime deprecation均为 SEMVER-MAJOR 级别punycode 运行时弃用node:punycode模块在运行时被标记为弃用此前已处于文档级弃用状态调用时会产生弃用警告util.promisify包装返回 Promise 的函数时运行时弃用对本身已返回 Promise 的函数再执行promisify会在运行时发出弃用警告。完整的 SEMVER-MAJOR 提交清单可在 v21.0.0.md 中查看其中包括构建工具链要求的提升如放弃 Visual Studio 2019 支持、上调 macOS/Xcode 最低版本、ICU 最低版本提升到 73、events.on/events.once的选项校验、net.server.maxConnections0语义修正等。若你的项目或依赖使用了被影响的能力升级到 Node.js 21 前应重点关注这些变更。如何获取与验证 Node.js 21你可以通过 下载页 或 Current 版本页 获取 Node.js 21 的安装包、二进制文件与源码。nodejs.org 的下载页会根据用户操作系统、架构与安装方式动态生成下载链接其 URL 生成逻辑集中在 url.ts 的getNodeDownloadUrl函数中例如 Linux x64 二进制对应node-v21.0.0-linux-x64.tar.xzmacOS Apple Silicon 对应node-v21.0.0-darwin-arm64.tar.gz。发布帖生成脚本 release-post/index.mjs 会从 changelog、SHASUMS、下载清单等数据源自动拼装每个版本的发布帖downloadsTable.mjs 中维护了各平台安装包/二进制/源码的完整命名清单同时downloadSnippets.mjs 负责收集各语言版本如snippets/en/download/下的 bash 片段的安装命令供下载页的代码框展示。你可以参照下载页提供的官方命令或访问 下载归档 查找历史版本。升级建议发布公告同时提醒Node.js 16LTS已到达 End-of-Life建议仍停留在 Node.js 16 的项目尽早规划升级到 Node.js 18LTS或 Node.js 20LTS。如果你的项目希望体验最新特性可以直接试用 Node.js 21并在测试环境验证应用与模块的兼容性——这将有助于确保你的项目与 Node.js 最新的变更和特性保持兼容。【免费下载链接】nodejs.orgThe Node.js® Website项目地址: https://gitcode.com/GitHub_Trending/no/nodejs.org创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考