Node.js 刚刚发布了 18.0.0 版本,内置了 fetch
、node:test
等标准模块。
一句话点评:std lib 在标准化,user lib 在精细化。
推荐用 fnm,nvs,nvm 等 Node.js 版本管理器。
$ fnm install 18
Installing Node v18.0.0 (arm64)
$ fnm use 18
Using Node v18.0.0
$ node -v
v18.0.0
需要注意的是,该版本不是 LTS 版本,请勿在生产环境使用,需要等到 2022-10-25 才会成为 LTS 版本。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9B2esUGC-1654486054112)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/012135a1091b40ef807c8b6e3919bcce~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image “https://github.com/nodejs/Release”)]
The project is also continuing its ‘Next 10’ effort. The goal of this effort is to reflect on what led to success in the first 10 years of Node.js and set the direction for success in the next 10.
Node.js 官方启动了 next-10 工作,并讨论出了未来重要的几件事:
譬如前面说的 Fetch 就和 Modern HTTP 的会议讨论有关,相关纪要。
6 月份的 OpenJS World 会议中将分享 ESM 和 Observability 进展,可以关注下相关动态。
前端同学应该都很熟悉fetch()
这个 API,它提供了标准的网络请求能力,取代了远古的 XMLHttpRequest 。
反观 Node.js 侧,官方提供的 http.request(),太底层太基础了,用起来往往需要大量的封装。譬如 302 后自动跳转、文件上传、响应结果解析等等。
因此在 Node.js 社区有非常多的上层请求库封装:
去年 Node.js 官方推出了 undici,一个非常现代化的库,具备优越的性能,良好的扩展性,内置的 mock 等能力,集大成者。
undici 的命名也很有趣:A HTTP/1.1 client → 11 → Eleven → Undici,即意大利语的 11。
从而 Node.js 终于内置了新的请求库,它遵循 Fetch 规范,底层就是基于 undici 来实现的。
const res = await fetch('https://nodejs.org/api/documentation.json');
if (res.ok) {
const data = await res.json();
console.log(data);
}
就这么简单,比 http.request() 那一坨 callback-style 代码简洁多了,平时写个脚本啥的,不用再引入额外的类库了。
全局增加了 fetch, FormData, Headers, Request, Response 这几个 API,以及 Web Streams API。
目前还处于默认开启的实验性特性阶段,文档在 Globals 章节,近乎没有,有需要直接看 MDN 文档 即可。
可能是为了遵循规范, undici 的很多能力如 Mock,Proxy,Pool 等都没有提供出来。
单元测试很重要,很多新兴的编程语言都是会内置对应的能力,但前端这块一直都是由社区来实现,前端同学耳熟能详的 Test Runner 有 Mocha、Jest。
// mocha showcase
import assert from 'assert/strict';
describe('test/index.test.js', () => {
it('test1', async () => {
const res = await fetch('https://nodejs.org/api/documentation.json');
assert(res.ok);
});
it.skip('skip some test', () => {});
});
终于,Node.js 在 18.x 里官方支持了 Test 能力:
import test from 'node:test';
import assert from 'assert/strict';
// 等价于 describe()
test('asynchronous passing test', async () => {
const res = await fetch('https://nodejs.org/api/documentation.json');
assert(res.ok);
});
test('multi level test', async (t) => {
// 等价于 it()
await t.test('subtest 1', (t) => {
assert.strictEqual(1, 1);
});
await t.test('subtest 2', (t) => {
assert.strictEqual(2, 2);
});
});
// 等价于 describe.skip() / it.skip()
test('skip option', { skip: true }, () => {});
// 等价于 describe.only() / it.only()
test('only option', { only: true }, () => {});
可以看到:
test()
,options 除了 skip 和 only 外,还支持 concurrency 并发。before/after/beforeEach/afterEach
能力,看 issue 描述会后续支持。类似覆盖率的演进过程,以前我们需要通过 nyc 对代码转译打桩,现在变为的 Node.js 内置覆盖率输出,nyc 变为 c8 这样的覆盖率报告生成工具。
后续 mocha 等估计会变为类似的上层封装,提供批量执行 和 Reporter 等能力。
简单的说,可以把某个 js 直接编译成 v8 snapshot,从而可以极大的提速启动时间。
目前这个版本,还只能通过 Node.js 源码来编译,且只能编译成 Node.js Runtime 的方式,即 Build-time。
# 把一段 markdown 渲染的逻辑,直接打包到 Node Runtime
$ cd /path/to/node/source
$ ./configure --node-snapshot-main=marked.js
$ make node
# 执行编译好的 Node Runtime
$ out/Release/node
> const html = globalThis.marked('# this is title');
秋怡正在继续推进该能力,未来可以无需编译 Node.js 源码:
$ node --build-snapshot --snapshot-blob marked.blob marked.js
$ node --snapshot-blob marked.blob
PS:这个能力用在命令行 CLI 的独立打包好像也不错。github.com/nodejs/node…
内置的 V8 引擎升级到 10.1 版本,值得注意的特性:
秋怡也写了一篇文章 Faster initialization of instances with new class features 分享了背后的实现。
PS:ECMAScript 双月报告:装饰器提案进入 Stage 3 ,阿里的 Node 架构团队今年会推动 Decorator 方案在 V8 的落地实现,不过肯定赶不上了,只能 Node.js 20.x 见了。
虽然在 18.x 中没有新的内容,但在过去的几个月中一直在持续推动 ECMAScript模块实现:
PS:CentOS 7 官方不再维护了,它对应的 glibc 版本太低,所以升不了。。。