Node.js v17 來了,看看都有哪些新功能?
Node.js v17 版本已發(fā)布,取代了 v16 做為當(dāng)前版本,新的 v17 版本提供了一些新功能:基于 Promise 的其它核心模塊 API、錯誤堆棧尾部增加 Node.js 版本信息、OpenSSL 3.0 支持、v8 JavaScript 引擎更新至 9.5。
基于 Promise 的 API
Node.js 項(xiàng)目的一項(xiàng)持續(xù)性戰(zhàn)略計(jì)劃是為 Node.js 核心模塊提供基于 Promise 的 API 支持,近年來已為 timer、stream 模塊提供了 Promise API 支持。
Node.js v17 版本為 readline 模塊提供了基于 Promise 的 API 支持。該模塊提供了一個(gè)接口用于從一個(gè)可讀流對象逐行讀取數(shù)據(jù)。
結(jié)合 process.stdin 可讀取用戶在終端輸入的數(shù)據(jù)。如下例所示:
- // test.mjs
- import * as readline from "node:readline/promises";
- import { stdin as input, stdout as output } from 'process';
- const rl = readline.createInterface({ input, output });
- const answer = await rl.question('“Nodejs技術(shù)棧” 的域名是什么:');
- console.log(`答案: ${answer}`);
- rl.close();
運(yùn)行之后,效果如下所示:
readline 模塊的更多信息參考 readline_readline。
錯誤堆棧增加 Node.js 版本
堆棧跟蹤是診斷應(yīng)用程序錯誤信息的重要組成部分,在 Node.js v17 版本中,如果因?yàn)橐恍┲旅腻e誤導(dǎo)致進(jìn)程退出,在錯誤堆棧的尾部將包含 Node.js 的版本信息。
如果想忽略該信息,運(yùn)行時(shí)在命令行指定 --no-extra-info-on-fatal-exception 標(biāo)志。
OpenSSL 3.0 支持
Node.js v17 版本包含了近期發(fā)布的 OpenSSL 3.0,根據(jù) OpenSSL 的發(fā)布策略,OpenSSL 1.1.1 將在 2023-09-11 結(jié)束支持,這個(gè)日期也在 Node.js v18 LTS 結(jié)束日期之前。
因?yàn)?OpenSSL 3.0 對允許的算法和密鑰大小增加了嚴(yán)格的限制,預(yù)計(jì)會對生態(tài)系統(tǒng)造成一些影響,在 Node.js v17 版本包含 OpenSSL 3.0 以便在下一個(gè) LTS 版本之前為用戶的測試和反饋留出時(shí)間。
例如,md4 這是 OpenSSL 3.0 默認(rèn)不再允許的一個(gè)算法,如果是在 Node.js 17 之前的 Node 版本中,應(yīng)用程序是可以正常運(yùn)行的,但在 Node.js v17 中將拋出一個(gè) error code 為 ERR_OSSL_EVP_UNSUPPORTED 的錯誤信息。
- import crypto from 'crypto';
- console.log(crypto.createHash('md4').update('123', 'utf8').digest('hex'))
Node.js v17 版本下運(yùn)行之后得到如下錯誤信息。
一個(gè)臨時(shí)的解決方法是運(yùn)行時(shí)增加 --openssl-legacy-provider 標(biāo)志,應(yīng)用程序不在報(bào)錯。
- $ node --openssl-legacy-provider test.mjs
- c58cda49f00748a3bc0fcfa511d516cb
V8 更新至 9.5
v8 在 8.1 版本開啟了 Intl.DisplayNames API,支持語言、區(qū)域、貨幣、腳本四種類型,現(xiàn)在添加了兩種新的類型:calendar、dateTimeField,分別返回不同的日歷類型和日期時(shí)間字段的顯示名稱。對于國際化應(yīng)用很有幫助。
- const esCalendarNames = new Intl.DisplayNames(['zh'], { type: 'calendar' });
- console.log(esCalendarNames.of('roc')); // 民國紀(jì)年
- const enCalendarNames = new Intl.DisplayNames(['en'], { type: 'calendar' });
- console.log(enCalendarNames.of('roc')); // Minguo Calendar
日期時(shí)間字段國際化名稱展示。
- function printDate(dateTimeField) {
- console.log(
- `${dateTimeField.of('year')} ${dateTimeField.of('month')} ${dateTimeField.of('day')}`
- );
- }
- printDate(new Intl.DisplayNames(['zh'], { type: 'dateTimeField' })) // 年 月 日
- printDate(new Intl.DisplayNames(['en'], { type: 'dateTimeField' })) // year month day
- printDate(new Intl.DisplayNames(['KOR'], { type: 'dateTimeField' })) // 년 월 일
- printDate(new Intl.DisplayNames(['THA'], { type: 'dateTimeField' })) // ปี เดือน วัน
Intl.DateTimeFormat API 在 v8 9.5 版本中為 timeZoneName 選項(xiàng)新增加了四個(gè)值:shortGeneric、longGeneric、shortOffset、longOffset。
通過以下代碼示例可看到之間的區(qū)別。
- console.log(new Intl.DateTimeFormat('zh').format(new Date())); // 2021/01/01
- console.log(new Intl.DateTimeFormat('zh', { timeZoneName: 'shortGeneric' }).format(new Date())); // 2021/01/01 中國時(shí)間
- console.log(new Intl.DateTimeFormat('zh', { timeZoneName: 'longGeneric' }).format(new Date())); // 2021/01/01 中國標(biāo)準(zhǔn)時(shí)間
- console.log(new Intl.DateTimeFormat('zh', { timeZoneName: 'shortOffset' }).format(new Date())); // 2021/01/01 GMT+8
- console.log(new Intl.DateTimeFormat('zh', { timeZoneName: 'longOffset' }).format(new Date())); // 2021/01/01 GMT+08:00
參見 v8 9.5 release 文檔 閱讀更多信息。
其它信息
按照 Node.js 發(fā)布時(shí)間表,Node.js v12 將于 2022 年 4 月結(jié)束生命周期。Node.js v16 在 2021 年 10 月 26 升級為 LTS,即長期支持版本。
Node.js 的奇數(shù)版本不是穩(wěn)定的版本(例如,當(dāng)前的 Node.js v17 ),它的生命周期很短,不要用于生產(chǎn)環(huán)境。
對 Node.js 版本信息不了的、不知道如何安裝 Node.js 的參考文章 “Node.js 版本知多少?又該如何選擇?”。
Reference
https://medium.com/the-node-js-collection/node-js-17-is-here-8dba1e14e382
https://nodejs.org/en/blog/release/v17.0.0/