Node.js 最新发布 v20.12.0,关注这些亮点功能!

发表时间: 2024-03-28 13:26

2024年03月26日,Node.js v20.12.0(LTS)版本正式发布。

下面来看看该版本带来的主要更新:

1.crypto:实现了 crypto.hash() 方法

在之前版本中,计算hash,使用的都是 crypto.createHash(algorithm[, options]) 方法,尤其在生成 md5 时特别方便。

此版本引入了一个辅助方法 crypto.hash(),可一次性计算输入内容的摘要。对于随时可用(非流式)的较小输入(<= 5MB),这比基于对象的 createHash() 快 1.2-2倍,而且由于不会创建中间对象,内存开销更少。

另外,在 Node.js v21.7.0 版本中也介绍了该特性更新。

const crypto = require('node:crypto');const name = 'FEDLAB';// 方案一:crypto.createHashconst hash = crypto.createHash('md5');hash.update(name);// 69382e924f0e37978b8cf2d292f7617bconsole.log(hash.digest('hex'));// 方案二:crypto.hash()// 69382e924f0e37978b8cf2d292f7617bconsole.log(crypto.hash('md5', name));

2. 加载和解析环境变量

正常情况下,我们会很自然的会选用 dotenv 包来管理 env 变量。

Node.js 20.12.0 版本提供了 process.loadEnvFile(path)util.parseEnv(content) 两个 API 来处理环境变量:

  • process.loadEnvFile(path):使用该函数可以加载指定 path 下的 .env 文件。如果未指定路径,则会自动加载当前目录下的 .env 文件。
  • util.parseEnv(content):使用该函数可以解析指定的环境变量内容。现在支持 .env 文件中的多行值。

.env 文件:

MULTI_LINE="HELLOWORLD"

代码示例:

process.loadEnvFile('./.env');/*打印{  ...,  MULTI_LINE: 'HELLO\nWORLD'}*/console.log(process.env);

3.新的连接尝试事件

net.createConnection 中新增了三个事件:

  • connectionAttempt:当尝试建立新连接时触发。在 Happy Eyeballs 的情况下,可能会发生多次。
  • connectionAttemptFailed:连接尝试失败时发出。如果是 Happy Eyeballs,可能会多次触发。
  • connectionAttemptTimeout:连接尝试超时:连接尝试超时时发出。在 Happy Eyeballs 的情况下,最后一次尝试将不会发出此信息。如果不使用 Happy Eyeballs,则根本不会发出此警报。

此外,还修正了以前的一个错误,即在前一次连接失败后,在连接被用户破坏后,可能会开始新的连接尝试。这将导致断言失败。

4.权限模型变更

Node.js 20.12.0 对实验性权限模型进行了多项修复,并新增了两项半重要提交。我们添加了一个新标志 --allow-addons 以在使用权限模型时启用附加组件。

node --experimental-permission --allow-addons

5.sea: 支持嵌入资源

现在,用户可以通过在配置中添加键路径字典作为 assets 字段来包含资源。在构建时,Node.js 会从指定路径读取资源并将其捆绑到准备 blob 中。在生成的可执行文件中,用户可以使用 sea.getAsset()sea.getAssetAsBlob() API 检索资源。

{  "main": "/path/to/bundled/script.js",  "output": "/path/to/write/the/generated/blob.blob",  "assets": {    "a.jpg": "/path/to/a.jpg",    "b.txt": "/path/to/b.txt"  }}

单一可执行应用程序可通过以下方式访问资源:

const { getAsset } = require('node:sea');// Returns a copy of the data in an ArrayBufferconst image = getAsset('a.jpg');// Returns a string decoded from the asset as UTF8.const text = getAsset('b.txt', 'utf8');// Returns a Blob containing the asset without copying.const blob = getAssetAsBlob('a.jpg');

6.vm: 支持使用默认 loader 处理动态导入

此版本添加了对使用 vm.constants.USE_MAIN_CONTEXT_DEFAULT_LOADER 作为 importModuleDynamically 选项的支持,适用于除 vm.SourceTextModule 之外的所有 vm API。这样,如果用户不需要自定义加载过程,就可以使用快捷方式在编译代码中支持动态 import(),而不会丢失编译缓存。当默认加载器通过此选项而非 --experimental-vm-modules 实际处理 import() 时,我们会发出实验警告。

const { Script, constants } = require('node:vm');const { resolve } = require('node:path');const { writeFileSync } = require('node:fs');// Write test.js and test.txt to the directory where the current script// being run is located.writeFileSync(  resolve(__dirname, 'test.mjs'),  'export const filename = "./test.json";');writeFileSync(resolve(__dirname, 'test.json'), '{"hello": "world"}');// Compile a script that loads test.mjs and then test.json// as if the script is placed in the same directory.const script = new Script(  `(async function() {    const { filename } = await import('./test.mjs');    return import(filename, { with: { type: 'json' } })  })();`,  {    filename: resolve(__dirname, 'test-with-default.js'),    importModuleDynamically: constants.USE_MAIN_CONTEXT_DEFAULT_LOADER,  });// { default: { hello: 'world' } }script.runInThisContext().then(console.log);

除了以上主要特性更新外,Node.js v20.12.0 版本还进行了其他部分特性更新及问题修复。