前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Node.js 2023 年终总结

Node.js 2023 年终总结

作者头像
童欧巴
发布2024-03-02 10:27:04
1430
发布2024-03-02 10:27:04
举报
文章被收录于专栏:前端食堂前端食堂

原文:https://blog.rafaelgss.dev/nodejs-2023-year-in-review

进入 2024 年已经两个月了,我想对 2023 年 Node.js 领域取得的成就做一个回顾。这份总结是由我个人挑选的,可能会漏掉一些贡献,因为 Node.js 的合作者们完成了大量的工作,有些领域如 WASI 我也需要更多的了解。

Node.js 正在迅速进化,对于日常用户来说,要跟上其最新的更新可能颇具挑战。即便是项目的开发者,也可能会忽略掉一些更新。因此,这篇文章旨在突出 2023 年 Node.js 生态中的重大变化和讨论。

作为参考,2023 年 nodejs/node#main 项目共有 2641 次代码提交。虽然这个数字看似微不足道,但对我来说,将其与历史数据对比非常有趣,这就是过去十年中主分支上提交次数的情况。

代码语言:javascript
复制
Between Jan 1 2023 ~ Jan 1 2024 = 2641
Between Jan 1 2022 ~ Jan 1 2023 = 2629
Between Jan 1 2021 ~ Jan 1 2022 = 2683
Between Jan 1 2020 ~ Jan 1 2021 = 3390
Between Jan 1 2019 ~ Jan 1 2020 = 3953
Between Jan 1 2018 ~ Jan 1 2019 = 4720
Between Jan 1 2017 ~ Jan 1 2018 = 4609
Between Jan 1 2016 ~ Jan 1 2017 = 3081
Between Jan 1 2015 ~ Jan 1 2016 = 2261
Between Jan 1 2014 ~ Jan 1 2015 = 1052

我使用了我自己创建的一个名为 nodejs-stats[1] 的小工具来获取这些信息。

看到像 Node.js 这样经过多年发展依然不断进化的成熟项目,真的非常令人钦佩。遗憾的是,我手上没有历史数据,但我强烈感觉到,今年 Node.js 吸引了许多首次贡献者。这部分原因可能归功于各种倡议,如 Grace Hopper 纪念日和不同的工作坊活动。比如,由我们团队在 2023 年的 NodeConfEU 上主持的“你的首次 Node.js 贡献”工作坊。我相信,项目的其他成员也在持续不断地帮助新贡献者 —— 如果你想为 Node.js 项目做出自己的第一份贡献,请随时联系我。我正在进行直播,指导人们熟悉 Node.js 的代码库。

Node.js Release

2023 年,Node.js 发布了 102 个不同版本线的更新,包括了安全更新。

代码语言:javascript
复制
$ git log --all --grep=', Version' --pretty=format:"%cs,%aN,%s" --since='Jan 1 2023' --before='Jan 1 2024' | wc -l
102

年初时,Node.js 有四个主要的版本线在维护:

  • Node.js 14
  • Node.js 16
  • Node.js 18
  • Node.js 19

其中,Node.js 14、Node.js 16 和 Node.js 19 已经进入了生命周期末期(EOL),而 Node.js 18 则进入了维护阶段,不再有新的常规更新。

到了年末,活跃的版本线更新为:

  • Node.js 18(维护中)
  • Node.js 20(长期支持 LTS)
  • Node.js 21(最新版本)

因此,如果你还未使用上述版本中的任何一个,请尽快升级。

在都柏林举行的 Node.js 合作者峰会(NodeConfEU)上,我们分析了 Node.js 二进制文件的下载统计,发现用户更新版本的速度并不如预期。这强化了我们的观点:用户需要更快地更新他们的 Node.js 版本。

如图显示,即便是已经结束生命周期(EOL)的版本,仍然有大量下载,这对 Node.js 用户构成了风险,因为他们可能会在某个时刻使用到一个存在安全漏洞的版本。因此,我们开始考虑一个可能的解释:我们的版本发布节奏可能过快。目前,有一个关于调整发布节奏的新提议正在讨论中,尚待发布团队的评估,该提议建议将每年的主要版本发布频率从两次减少到一次。

在详细分析上述的下载量图表时,尤其是仔细观察 y 轴数据,你可能会得出一个结论,认为 Node.js 的下载量在 3 月 23 日达到了大约 6000 万的峰值。但这种解读并不完全准确,因为它忽略了 NodeSource 的分发统计数据,后者主要涵盖了生产环境中的二进制文件,并没有包括那些不再活跃的版本线(如 Node.js 8、10、12 等)的下载量。为了更全面地了解 Node.js 的分发机制,我建议你深入阅读《Node By Numbers 2021~2022》[2]一文,因为深入探讨这一主题已超出了本文的范畴。

金丝雀在金矿中(CITGM)的积极进展

@nodejs/releasers 在 Node.js 生态中扮演着至关重要的角色。他们保障了你设备上运行的版本的稳定性。为达成这一目的,我们部署了一套全面的测试,涵盖所有支持的架构,并且针对特定的更改执行特定测试,如针对 V8 引擎的测试。此外,对于每次发布,我们都会运行 CITGM(金丝雀在金矿中测试),这一过程会拉取 lookup.json 文件中列出的所有模块,并使用新的候选版本运行它们的测试套件。如遇任何问题,我们将进行深入调查,并有时需要模块作者的指导。

然而,CITGM 需要强大的计算资源来正确完成所有测试。遗憾的是,我们在这方面受到一定的限制,这导致了一些测试之间出现并发错误。这是因为某些测试必须并行执行,否则 CITGM 的完成可能需要很长时间。保持 lookup.json 文件中列出的模块最新是另一个挑战。有时候,一些模块可能会被存档,或许永远不会支持 Node.js 的新版本,或者它们可能本身就不太稳定(这种情况相当普遍)。

因此,我们经常看到一些措施,如:

  • 宣布某些 CITGM 模块无法维护
  • 剔除被跳过的模块

如果不这么做,我们可能会遇到一个不可靠的 CITGM,使我们对可能的重大变化猝不及防。

Node.js 项目的新走向

首先,我要明确这篇文章只代表我的个人看法,并非代表整个项目。

作为项目的长期成员,及自 2022 年起加入技术指导委员会(TSC),我注意到项目现在比以往更开放于重大的改变。这其中包括一些看似不那么直接相关的发展,如将新的依赖整合至核心,以及开发新的内置模块。这使得 Node.js 作为一个平台的范围得到了扩展。然而,在我看来,这种新策略可能会带来关于维护和潜在安全风险的担忧。但从好的方面来看,它也增强了开发者的能力,并减少了使用恶意库的风险,尽管这可能会影响到原生端的性能。为大家提供一个参考,我一直在跟踪 Node.js 不同版本的二进制文件大小,显而易见,加入的新依赖和功能直接影响了其二进制文件的大小。

除非你的运行环境特别受限,否则 100MiB 的大小增加不应该是一个令人担忧的问题。

新引入的依赖

Node.js 将外部依赖打包进了其二进制文件中:

代码语言:javascript
复制
{
  node: '21.6.0',
  acorn: '8.11.3',
  ada: '2.7.4',
  ares: '1.20.1',
  base64: '0.5.1',
  brotli: '1.1.0',
  cjs_module_lexer: '1.2.2',
  cldr: '44.0',
  icu: '74.1',
  llhttp: '9.1.3',
  modules: '120',
  napi: '9',
  nghttp2: '1.58.0',
  nghttp3: '0.7.0',
  ngtcp2: '0.8.1',
  openssl: '3.0.12+quic',
  simdjson: '3.6.3',
  simdutf: '4.0.8',
  tz: '2023c',
  undici: '5.28.2',
  unicode: '15.1',
  uv: '1.47.0',
  uvwasi: '0.0.19',
  v8: '11.8.172.17-node.19',
  zlib: '1.3.0.1-motley-40e35a7'
}

2023 年,Node.js 引入了三个新的依赖库:

  • Ada - 一个符合 WHATWG 标准的高速 URL 解析器,采用现代 C++ 编写。
  • simdutf - 一个处理 Unicode 编码(UTF8、UTF16、UTF32)的解析库。
  • simdjson - 一个使用广泛可用的 SIMD 指令和微并行算法来高效解析 JSON 的库。

这些库都致力于提升性能,正如你在《2023 年 Node.js 性能报告》[3]中看到的,它们使 Node.js 在性能改进方面达到了新的高度。

OpenSSL 3.0.x 对于 QUIC 的性能影响

从 16 版本开始,Node.js 开始使用 quictls 团队提供的 OpenSSL 分支。这是为了将 QUIC 协议引入 Node.js 所必需的第一步。然而,与 OpenSSL 3.2.x 相比,OpenSSL 3.0.x 的性能显著较差。从 Node.js 的视角出发,迁移到 OpenSSL 3.2.x 面临两大挑战:

  • 它不完全支持 QUIC — 虽然 Node.js 还未正式支持 QUIC。
  • OpenSSL 3.2.x 不是长期支持(LTS)版本 — 对 Node.js 中的 LTS 版本来说,使用一个在生命周期结束后可能存在安全漏洞的版本是不可取的。

如果需要更多背景信息,请参考 #51152[4]。关于性能,你可以参考我的 GitHub 仓库 nodejs-bench-operations[5],该仓库提供了加密操作的性能基准。

Node.js 的持续性能演进

如《Node.js 性能状况 2023》报告所述,Node.js 在性能方面持续稳步发展。本节不会深入探讨具体数值数据(这将在《Node.js 性能状况 2024》中详细报道),而是重点介绍那些在性能领域取得明显进步的倡议和 PR。

一个值得注意的进步是 libuv 升级至 1.45.0 版本。此版本在 Linux 上启用了 IO_URING,使得文件系统操作(如 read、write、fsync、fdatasync、stat、fstat 和 lstat)的吞吐量提高了 8 倍。更多详情见对应的 pull 请求:libuv/libuv#3952[6]。

此外,在 2023 年,我们为 Node.js 引入了新的 URL 解析器 Ada,现已在所有活跃的版本线(18、20 和 21)中提供。详细信息请见 pull 请求:nodejs/node#46410[7]。

2023 年发现两个重要的性能回归问题:

  • AsyncHooks
  • WebStreams

这些特性对于 Node.js 的某些使用场景至关重要。比如,使用 fetch() 时可能会依赖 WebStreams,或在使用任何应用性能监控(APM)工具时,应通过 AsyncLocalStorage

一个在 1 月份开始的倡议,在问题记录 #46265 中提出了一个替代方案,旨在实现不依赖于 AsyncHooks 的 AsyncLocalStorage。当时,AsyncHooks 被认为是性能瓶颈。与此相关的工作已经通过拉取请求 #46387 和 #48528 得到了执行。

2022 年,WebStreams 在 fetch 函数中被发现是性能瓶颈,正如问题评论中所强调的。自那以后,我们不断通过多个 PR 提升了其在 undici 中的应用效率,包括:

  • nodejs/node#46086[8]
  • nodejs/node#47956[9]

对于那些关注 Node.js 性能表现的人,我特别推荐关注 nodejs/performance[10] 仓库并参与他们的会议。务必关注性能标签,以获取更新,如 nodejs/node#49745[11] 和 nodejs/node#49834[12] 这样的 PR,它们旨在提高常规 Node.js 流的性能。

原生基准测试模块

在2023年,Node.js 差点新增了一个原生的基准测试模块。我和我的同事 Vinicius Lourenco 一起提交了一个拉取请求,这个请求为 Node.js 引入了一个试验性的基准测试模块:通过 require('node:benchmark') 使用。

尽管这个请求引起了广泛的关注,但我们因为以下几个原因没有继续深入:

  • 基准测试非常复杂,特别是微基准测试更是如此。评估它们的难度很大,且很难验证其准确性,因为存在多种测量策略。想要了解更多,请查看我的《准备和评估基准测试》文章。当时,我分配给 Node.js 不同领域的工作资源有限,没有余力扩展对这个主题的研究。
  • 一些 Node.js 的贡献者表示了他们的担忧,正如我之前提到的,当时我并没有足够的时间和精力来详细探讨这个问题。

不过,这并不意味着我们就此放弃了!我们最终以 bench-node 的名称在 npmjs 上发布了这个模块 —— 是的,我们还没想到更好的名字。不妨去看看,并给它加个星标 ⭐ https://github.com/RafaelGSS/bench-node/。

Node.js 安全增强

2023 年,我主要致力于 Node.js 的安全领域。我与 OpenSSF 合作,全时间专注于 Node.js 安全性的开发与提升。在这一节中,我会简要介绍我们讨论过的主题、实施的功能、工作流程等。非常重要的一点是,我要向 Node.js 安全团队的所有成员表示衷心的感谢,感谢他们在过往及当前项目中的支持与帮助。同时,也要感谢 Node.js 审查团队在处理 HackerOne 报告方面给予我的帮助。对 Tobias Nießen 的特别感谢,他在发现和解决 Node.js 核心问题方面付出了巨大努力。

Node.js 权限模型

让我们从 2023 年我个人非常看重的一个安全里程碑谈起——这可能有点主观——Node.js 权限模型。这个项目最初是由 Anna Henningsen 和 James Snell提出的,但直到 2022/2023 年我才对其进行了重新实现和完善。如果你对这个功能背后的深层次原理感兴趣,我在 NodeConf EU 上做了一个关于它的演讲:“Node.js权限模型的发展之旅”[13]。

从技术角度讲,这个实验性功能允许你限制对以下环境资源的访问:

  • 文件系统(特指fs模块)- 读/写权限
  • Inspector协议
  • Worker线程
  • 子进程
  • 原生插件

使用方法非常简单,仅需在启动Node.js进程时加上--experimental-permission参数,并通过--allow-*标志来指定允许的操作。例如,如果我想为我的应用入口点设置只读权限。

代码语言:javascript
复制
$ node --experimental-permission --allow-fs-read=./index.js index.js

因此,如果尝试从其他路径读/写,就会出现错误:

代码语言:javascript
复制
// index.js
const fs = require('fs')
const data = fs.readFileSync('/etc/passwd')
console.log(data.toString())
代码语言:javascript
复制
node:fs:581
  return binding.open(
                 ^

Error: Access to this API has been restricted
    at Object.openSync (node:fs:581:18)
    at Object.readFileSync (node:fs:460:35)
    at Object.<anonymous> (/home/rafaelgss/index.js:3:17)
    at Module._compile (node:internal/modules/cjs/loader:1378:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1437:10)
    at Module.load (node:internal/modules/cjs/loader:1212:32)
    at Module._load (node:internal/modules/cjs/loader:1028:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:142:12)
    at node:internal/main/run_main_module:28:49 {
  code: 'ERR_ACCESS_DENIED',
  permission: 'FileSystemRead',
  resource: '/etc/passwd'
}

Node.js v21.6.1

此外,还可以在官方文档[14]中找到相关信息。

处理更多安全发布

在 2023 年,我们发布了更多安全更新,这主要得益于我们对第三方 CVE 的主动应对措施加强了。根据《Alpha-Omega Node.js 报告 2022》的描述,2022 年安全团队启动了若干倡议,这些倡议的成果在 2023 年得到了显现。这些倡议包括更新自动化和 Node.js 发布影响的自动化,这些都加快了我们团队响应漏洞的速度。

随着权限模型的引入,我们发现人们也开始关注 Node.js 从 11.8.0 版本起就已经存在的另一项实验性安全功能:策略机制。这项功能属于我们所定义的模块化权限范畴,我们在 2023 年修复了该功能中的数个漏洞。

安全更新如下:

  • 2024 年 2 月安全更新[15]
  • 2023 年 10 月安全更新[16]
  • 2023 年 8 月安全更新[17]
  • 2023 年 6 月安全更新[18]

在报告方面,我们对我们的威胁模型进行了一些明确的说明。实验性功能,如权限模型和策略机制,其严重性级别可以与任何稳定功能相媲美。因此,在审阅 Node.js 的安全更新时,请确保检查漏洞是否影响到你。我们常常修补的“高”危漏洞,往往只影响使用该功能的用户。

站点更新

在 2023 年,大家讨论了给 Node.js 网站更新换代,让它焕然一新,具体讨论可参见此处。这个想法不仅在 TSC 会议上被多次提及,还在 Node.js Collab 峰会上得到了分享。这项更新是一项包含多个步骤的庞大工程,我想特别感谢 @nodejs/website 团队的每一个成员,为了这次更新他们付出了巨大的努力。详细信息如下:

即将推出的下载页面:

Draft PR: nodejs/nodejs.org#6353[19]

功能更新

2023 年,Node.js 推出了多项新功能,由于篇幅限制,不可能在一篇文章中对每一项进行详尽的介绍。因此,本文将重点介绍一些重要的更新,欢迎大家深入探索!

  • 单一可执行应用(实验性):这一功能首次出现在 Node.js 19 版本,并在 Node.js 20.0.0 发布后受到更多关注。它使得 Node.js 应用可以轻松分发到未安装 Node.js 的系统上。需要注意的是,这还是一个实验功能,值得你尝试体验。
  • 内置 .env 支持(实验性):Node.js 20.6.0 版本带来了官方的环境变量配置文件读取机制,此前通常依赖 dotenv 包或类似方法。现在,你可以直接在 Node.js 中使用此功能,无需安装额外的包。详细信息可查阅 —env-file 文档[20]。
  • WebSocket 客户端(实验性):Node.js 21.0.0 版本引入了内置的 WebSocket 客户端(需通过标志启用),此功能遵循 WHATWG WebSocket 规范,通过 --experimental-websocket 标志启用。
  • 测试运行器(稳定):虽然这个功能不是在 2023 年发布的,但去年该 API 添加了许多功能,并标记为稳定。新增的功能包括函数模拟支持、时间(MockTimers API)模拟、测试报告以及分片支持等。详情请查阅 API 文档[21]。

在诊断领域,核心部分添加了一些重要的 PR:

  • GC 配置文件支持:通过 PR #46255,你现在可以使用 v8.GCProfiler 来获取垃圾收集器(GC)的度量数据。这提供了一种直接获取这些信息的新方法。
  • 新的 Tracing Channel API:通过 PR #44943 引入,提供了一个新的 API 通过一系列通道跟踪操作,旨在为 Node.js 应用提供必要的可观测性,同时保证性能和可靠性。
  • 对 V8 Maglev 编译器的支持:V8 在 2022 和 2023 年间推出了 Maglev 新编译器,Node.js 通过构建标志首次支持,后来默认启用。这是一个重大更新,将在 Node.js 22 版本中默认启用,预计在 2024-04-23 发布。

HTTP 和 WHATWG 规范也有重要更新:

  • fetch 功能现已稳定。
  • 默认启用 autoSelectFamily,该变更影响了部分系统的兼容性。
  • Duplex.from() 现支持 WebStreams。
  • Readable 和 Writable Streams 实现了 finished() 方法。

此外,针对 fetch 性能的分析发现 WebStreams 是主要瓶颈之一,2023 年对其进行了多项优化,包括状态错误的重用,这在特定基准测试中提高了 fetch 的性能约 23%。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-02-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端食堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Node.js Release
    • 金丝雀在金矿中(CITGM)的积极进展
      • Node.js 项目的新走向
      • 新引入的依赖
        • OpenSSL 3.0.x 对于 QUIC 的性能影响
          • Node.js 的持续性能演进
            • 原生基准测试模块
            • Node.js 安全增强
              • Node.js 权限模型
                • 处理更多安全发布
                  • 站点更新
                  • 功能更新
                  相关产品与服务
                  腾讯云服务器利旧
                  云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档