新一代 Node.js 20 来了!
声明:本文是根据官方英文文档翻译而来。如有疑问,请参阅原始英文文档
我们很高兴地宣布发布 Node.js 20!亮点包括全新的 Node.js 权限模型、同步 import.meta.resolve
、稳定的 test_runner,将 V8 JavaScript 引擎更新至 11.3 版本,Ada 更新至 2.0 等等!
该项目在许多领域继续取得进展,许多新功能和修复流入现有的LTS版本。因此,Node.js 20变更日志中概述的更改仅代表自上一个主要发布以来的一小部分功能和工作。本博客文章将为这些变化提供一些额外的背景信息。
您可以在 github.com/nodejs/rele… 上了解更多关于我们的发布政策。
要下载 Node.js 20.0.0,请访问:nodejs.org/en/download… 您可以在 nodejs.org/en/blog/rel… 找到发布帖子,其中包含此版本中包含的所有提交的完整列表。
请注意,Node.js 20 将于十月进入长期支持(LTS)阶段,在此之前,未来六个月它都是“Current”版本。 我们鼓励您探索这个最新版本提供的新功能和优点,并评估它们对您的应用程序可能产生的影响。
显著变化
权限模型
Node.js 权限模型是一种实验性机制,用于在执行期间限制对特定资源的访问。
在包含权限模型的第一个版本中,该功能具有以下能力:
- 限制对文件系统的访问(读和写)
- 使用
--allow-fs-read
和--allow-fs-write
- 使用
- 限制对 child_process 的访问
- 使用
--allow-child-process
- 使用
- 限制对 worker_threads 的访问
- 使用
--allow-worker
- 使用
- 限制对本地插件的访问(与
--no-addons
标志相同)
可用的权限由 --experimental-permission 标志记录。
使用 --experimental-permission
启动 Node.js 时,将限制访问文件系统、生成进程和使用 node:worker_threads
的能力。
现在,使用 Node.js 的开发者可以通过引入 --allow-fs-read
和 --allow-fs-write
标志来更好地控制文件系统的访问。这些实验性功能允许更细粒度地控制哪些部分的文件系统可以被 Node.js 进程访问。
要启用这些标志,开发人员可以使用 --experimental-permission
标志以及所需的权限。例如,运行以下命令可允许对整个文件系统进行读写操作:
$ node --experimental-permission --allow-fs-read=* --allow-fs-write=* index.js
开发者还可以通过将逗号分隔的值传递给标志来指定文件系统访问的特定路径。例如,以下命令允许对 /tmp/
文件夹进行写入访问:
$ node --experimental-permission --allow-fs-write=/tmp/ --allow-fs-read=/home/index.js index.js
通配符模式也可以用于允许一次访问多个文件或文件夹。例如,以下命令允许读取 /home/
目录中以 test
开头的所有文件和文件夹:
$ node --experimental-permission --allow-fs-read=/home/test* index.js
当启用权限模型时,可以使用 process
对象的新属性 permission
在运行时检查是否已授予某个特定权限。
process.permission.has('fs.write'); // true
process.permission.has('fs.write', '/home/nodejs/protected-folder'); // true
需要注意的是,这些功能仍处于实验阶段,并且可能会在未来的 Node.js 版本中进行更改。
此外,可以在权限模型文档中找到更多信息。
权限模型由 Rafael Gonzaga 在 #44004 中贡献。
自定义 ESM loader hooks 接近稳定
通过加载器 (--experimental-loader=./foo.mjs
) 提供的自定义 ES 模块生命周期钩子现在在一个专用线程中运行,与主线程隔离。这为加载器提供了单独的作用域,并确保没有加载器和应用程序代码之间的交叉污染。
为了与浏览器行为一致,import.meta.resolve()
现在返回同步;请注意,用户加载器中的 resolve
钩子仍然可以是异步的,如果 loader 作者希望,在应用程序代码中 import.meta.resolve
仍将返回同步。
这些更改是标记 ESM 加载程序稳定之前最后未完成的项目。一旦社区报告了一段时间内没有重大错误,我们打算将 loaders 标志、import.meta.resolve
和 resolve
和 load
钩子标记为稳定。这应该能够促进 ESM 的更广泛采用,因为重要利益相关者如工具厂商将拥有一个稳定的 API 来构建分析和报告库。
由 Anna Henningsen、Antoine du Hamel、Geoffrey Booth、Guy Bedford、Jacob Smith 和 Michaël Zasso 在 #44710 中贡献。
V8 JavaScript 引擎更新至 11.3 版本
和以往一样,Node.js 中包含了 V8 引擎的新版本(更新到 11.3 版本,是 Chromium 113 的一部分),带来了改进的性能和新的语言特性,包括:
- String.prototype.isWellFormed and toWellFormed
- Methods that change Array and TypedArray by copy
- Resizable ArrayBuffer and growable SharedArrayBuffer
- RegExp v flag with set notation + properties of strings
- WebAssembly Tail Call
V8 引擎更新由 Michaël Zasso 在 #47251 中贡献。
稳定的 Test Runner
最近更新的 Node.js 版本 20 中,test_runner 模块有一个重要变化。该模块在最近一次更新后被标记为稳定版。稳定的测试运行器包括编写和运行测试所需的基本组件,包括:
describe
、it
/test
和hooks来构建测试文件- mocking(模拟)
- watch mode(监视模式)
node --test
用于并行运行多个测试文件
Test Runner 还包含一些尚未稳定的部分,包括报告生成和代码覆盖率。
以下是使用该测试运行器的简单示例:
import { test, mock } from 'node:test';
import assert from 'node:assert';
import fs from 'node:fs';
mock.method(fs, 'readFile', async () => "Hello World");
test('synchronous passing test', async (t) => {
// This test passes because it does not throw an exception.
assert.strictEqual(await fs.readFile('a.txt'), "Hello World");
});
由 Colin Ihrig 在 #46983 中贡献
性能
随着新成立的 Node.js 性能团队,自上一个主要版本发布以来,性能得到了重新关注。Node.js 20 包含了许多对运行时基本部分的改进,包括 URL
、fetch()
和 EventTarget
。
初始化 EventTarget
的成本减少了一半,提供更快速地访问所有使用它的子系统。此外,在 API (如URL.canParse()
和计时器)中利用V8 Fast API调用来提高性能。
Node.js 20 包括特定的更改,例如更新后的 Ada 2.0 版本,这是一个快速且符合规范的C++ URL解析器。
展望未来改善性能的新方法,我们目前正在努力通过重构来消除流、URL
、URLSearchParams
和 String Decoder 上品牌验证检查所带来的遵循规范成本。这有助于支持我们在有意义之处遵循规范的总体目标。
如果您热衷于性能和Node.js,则我们正在积极寻找贡献者加入我们的性能团队。
EventTarget 初始化的成本减少了一半,为所有使用它的子系统提供了更快的访问速度。此外,Node.js 20 还利用了 V8 Fast API 调用来提高诸如 URL.canParse() 和计时器等 API 的性能。
Node.js 20 还包括一些特定的变化,例如更新了 2.0 版本的 Ada,这是用 C++ 编写的一款快速且符合规范的 URL 解析器。
我们期待通过新的方法来提高性能,目前正在努力通过重构来降低遵循规范的成本,以消除对流、URL、URLSearchParams 和 String Decoder 的品牌验证检查。这有助于支持我们在合理的情况下遵循规范的总体目标。
如果您对性能和 Node.js 充满热情,我们正在积极寻找贡献者加入我们的性能团队。
Preparing single executable apps now requires injecting a Blob
在过去的一年里,该项目一直在为单个可执行应用程序(SEA)提供支持,最近初步支持已经实现。随着功能仍处于实验阶段,团队继续完善这一方法。在 Node.js 20 中,构建单个可执行应用程序现在需要从 JSON 配置中注入由 Node.js 准备的 blob,而不是注入原始的 JS 文件。
例如:
sea-config.json
{
"main": "hello.js",
"output": "sea-prep.blob"
}
将 blob 写入 sea-prep.blob 文件。
$ node --experimental-sea-config sea-config.json
这个二进制 blob 现在可以被注入到二进制文件中。
这个改变是为了允许将多个共存的资源嵌入 SEA(单一可执行应用程序)中,从而开启新的使用场景。
由 Joyee Cheung 在 #47125 中贡献。
Web Crypto API
该项目致力于与其他 JavaScript 环境的互操作性。例如,在 Node.js 20 中,Web Crypto API 函数的参数现在按照它们的 WebIDL 定义进行强制转换和验证,就像其他 Web Crypto API 实现一样。这进一步提高了与其他 Web Crypto API 实现之间的互操作性。
由 Filip Skokan 在 #46067 中贡献。
ARM64 Windows 的官方支持
Node.js 具有广泛的平台和架构支持,人们似乎希望它能在任何地方运行。我们很高兴地宣布,Node.js现在包括了适用于ARM64 Windows的二进制文件,使其能够在该平台上进行本地执行。MSI、zip/7z 包和可执行文件可以从 Node.js 下载站点以及所有其他平台一起获得。CI 系统已更新,并且现在所有更改都已完全测试通过 ARM64 Windows,以防止回归并确保兼容性。
ARM64 Windows 在 #47233 中被 Stefan Stojanovic 升级为二级支持。
Web Assembly System Interface (WASI) 的进展
该项目继续在 Node.js 中实现 WASI。一些值得注意的进展是,虽然它仍处于试验阶段,但不再需要命令行选项来启用 WASI。这应该使其更易于使用。WASI 开发的团队期待着发布 preview2
版本,还对未来进行了一些计划性变更。当 new WASI()
被调用时,需要添加一个 version
选项。在 20.x 版本中,version
是必需的,且没有默认值。这很重要,因为当支持新版本时,应用程序不会默认使用可能已过时的版本。然而,这意味着任何依赖于默认版本的代码都需要更新以请求特定版本。
如果您有兴趣在 Node.js 或 uvwasi 中使用 WASI,并且希望成为贡献者,请联系该团队。
呼吁行动!
请大家尝试新的 Node.js 20 版本!我们非常乐意听取您的反馈。使用 Node.js 20 测试您的应用程序和模块有助于确保您的项目与最新的 Node.js 变化和功能具有未来兼容性。值得注意的是,Node.js 14 将在 2023 年 4 月停止维护, 因此我们建议您开始计划升级到Node.js 18(LTS)或即将成为LTS的 Node.js 20。请注意, Node.js16(LTS)将在 2023 年 9 月停止维护, 并提前从原定于2024年4月结束支持以配合OpenSSL1.1.1支持结束时间。 您可以在 nodejs.org/en/blog/ann… 上阅读更多关于该决定的详细信息。展望未来,Next-10 团队正在进行一项调查以收集生态系统信息,请参与并帮助塑造 Node.js 的未来,在这里提交您的反馈意见。
转载自:https://juejin.cn/post/7223775785206874149