Node.js 20 已经在 2023 年 4 月 18 日发布了,并且将于 2023 年 10 月进入长期支持(也就是 LTS 版本)。我们可以通过这里下载并体验:https://nodejs.org/en/download/current/
在 Node.js 20 中,有非常多的新变化和亮点,包括新的 Node.js 权限模型、同步的import.meta.resolve
、稳定版的test_runner
、升级到 11.3 版本的 V8 引擎等等。
Node.js 20 运行时做了非常多的性能优化,主要包括URL
模块、fetch()
函数和EventTarget
模块。
初始化EventTarget
的开销减少了一半,所有依赖了这个模块的子系统都可以更快速的访问。
另外,还使用V8 Fast API
(一个用于快速调用 C 函数的 API,详见这里)来提高 URL.canParse()
和计时器等 API 的性能。
同时,将Ada
更新到了 2.0,这是一种用C++
编写的性能极佳的 URL 解析器,用于获取更好的 URL 解析性能。
最后,开发团队也在通过重构的手段来优化stream
、URL
、URLSearchParams
和字符串解码器的性能。
Node.js 权限模型目前仍然是实验性的功能,用于在执行期间限制对特定资源的访问。具体包含以下功能:
--allow-fs-read
和--allow-fs-write
限制对文件读写系统的访问--allow-child-process
限制访问 child_process--allow-worker
限制访问 worker_threads--no-addons
制对本机插件的访问通过引入--allow-fs-read
和--allow-fs-write
,Node.js 开发者可以更好地控制文件系统访问。这些实验性功能允许更精细地控制 Node.js 进程对于文件系统的访问。
要启用这些标志,开发人员可以使用--experimental-permission
,并在后面加上所需的权限。例如,运行以下命令允许对整个文件系统进行读写访问:
$ node --experimental-permission --allow-fs-read=* --allow-fs-write=* index.js
此命令还支持通配符模式,例如,以下命令允许/home/
目录中以test
开头的所有文件和文件夹进行读取访问 test:
$ node --experimental-permission --allow-fs-read=/home/test* index.js
通配符模式也可用于允许一次访问多个文件或文件夹。例如,以下命令允许对/home/目录中以 开头的所有文件和文件夹进行读取访问 test:
$ node --experimental-permission --allow-fs-write=/tmp/ --allow-fs-read=/home/index.js index.js
启用权限模型后,可以使用 process.permission
来检查权限。
process.permission.has("fs.write"); // true
process.permission.has("fs.write", "/home/nodejs/protected-folder"); // true
详细文档:https://nodejs.org/api/permissions.html#process-based-permissions
相关 PR:https://github.com/nodejs/node/pull/44004
在 Node.js 中,我们可以通过ESM loader
的生命周期钩子,也就是--experimental-loader=./foo.mjs
这种形式来加载 ESM 模块。而现在 Node.js 20 支持了将加载模块放在与主线程隔离的专用线程中运行。这为加载模块提供了一个单独的作用域,并且确保了加载的模块和应用程序代码之间没有交叉污染。另外,为了与浏览器行为一致,import.meta.resolve()
现在默认为同步返回。
上述这些是ESM loader
进入 stable 阶段之前的最后几项未完成的更改。当上述改动趋于稳定后,官方会将这些功能标记为 stable。这为 Node.js 应用更广泛地使用 ESM 打下了基础。
相关 PR:https://github.com/nodejs/node/pull/44710
Node.js 20 中将 V8 引擎升级到了 11.3(是 Chromium 113 的一部分)。而新的引擎带来了如下新功能:
String.prototype.isWellFormed
和 toWellFormed
。
isWellFormed
用于检查这个字符串是否是一个合法的 Unicode,而toWellFormed
则会将一个字符串转换为 Unicode。Array.prototype
和TypedArray.prototype
的函数会直接修改接收的数组。而新函数会返回接收的数组的修改副本,并将原始数组保持不变。这些新函数在数据不可变的编程风格中很有用。v
标志,并对+
进行拓展。
/[\p{Script_Extensions=Greek}&&\p{Letter}]/v
匹配所有希腊字母。相关 PR:https://github.com/nodejs/node/pull/47251
test_runner
模块在 Node.js 20 中已经进入了 stable 阶段,它主要用来编写并运行测试文件,包括:
describe
/it
/test
函数,以及测试文件的钩子。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 ZY");
test("synchronous passing test", async (t) => {
// This test passes because it does not throw an exception.
assert.strictEqual(await fs.readFile("zy.txt"), "Hello ZY");
});
相关 PR:https://github.com/nodejs/node/pull/46983
单一可执行应用 (Single Executable Applications, SEA)是指无需依赖 Node.js 环境,可以直接在操作系统中执行的程序。一般开发者会选择pkg
、boxednode
等社区方案来讲一个 Node.js 应用打包成一个可执行文件。Node.js 在 2022 年成立了相关团队,负责提供官方的 SEA 生成方案。截止到目前,SEA 相关的功能依旧是实验性的功能。
在 Node.js 20 中,构建单一可执行应用现在需要从 JSON 配置中注入由 Node.js 准备的 blob,而不是注入原始 JS 文件,这项改动是为了允许将多个共享资源嵌入到 SEA 中。
举个例子:
sea-config.json
{
"main": "hello.js",
"output": "sea-prep.blob"
}
这会将 blob 写入文件 sea-prep.blob
。
$ node --experimental-sea-config sea-config.json
这样,就可以将此 blob 注入到二进制文件中了。
相关 PR:https://github.com/nodejs/node/pull/47125
在 Node.js 20 中,将 Web Crypto API 的各个函数参数按照 WebIDL 的标准进行了修改,使之与浏览器等其它 Web Crypto API 实现对齐。这进一步提高了 Node.js 的 Web Crypto API 与其他实现的互操作性。
相关 PR:https://github.com/nodejs/node/pull/46067
Node.js 支持非常多的平台和架构,开发者们希望它可以在任何环境下运行。而一个好消息是,Node.js 20 现在支持在 ARM64 Windows 环境下运行了!
相关 PR:https://github.com/nodejs/node/pull/47233
虽然在 Node.js 中,WASI 相关功能依旧是实验性的,但在 Node.js 20 中,我们已经不再需要使用命令行选项来启用 WASI。另外就是在new WASI()
实例化 WASI 对象时,需要默认传入一个version
参数来明确它所对应的版本。
Node.js 14 将于 2023 年 4 月结束它的生命周期,Node.js 16 (LTS) 也将于 2023 年 9 月结束生命周期。
因此是时候开始考虑将 Node.js 升级到 Node.js 18 (LTS) 或 Node.js 20(即将成为 LTS)了!