Node.js 18 新特性抢先看

共 3689字,需浏览 8分钟

 ·

2022-04-30 12:30

本文适合对Node.js感兴趣的小伙伴阅读~

欢迎关注前端早茶,与广东靓仔携手共同进阶~

一、前言

本文基于开源项目:

https://nodejs.org/en/blog/announcements/v18-release-announce/

https://nodejs.org/en/blog/release/v18.0.0/

Node.js 发布了 18.0.0 版本,内置了 fetchnode:test 等标准模块。
简单概括:std lib 在标准化,user lib 在精细化。

二、快速体验

推荐用 fnmnvsnvm 等 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 版本。

三、展望未来

该项目还在继续其“Next 10”的努力。这项工作的目标是反思导致 Node.js 前 10 年成功的原因,并为下一个 10 年的成功设定方向。


Node.js 官方启动了 next-10 工作,并讨论出了未来重要的几件事

  • 现代化的 HTTP
  • 友好的类型支持
  • 对初学者更友好的渐进式文档
  • 对 ECMAScript 规范的支持和及时跟进
  • 可观测性,包括 logging/metrics/tracing,以及 APM 等
  • 更好的多线程支持
  • 支持打包为单文件的分发方式

6 月份的 OpenJS World 会议中将分享 ESM 和 Observability 进展,可以关注下相关动态。

四、Fetch API

小伙伴们应该都很熟悉fetch()这个 API,它提供了标准的网络请求能力,取代了远古的 XMLHttpRequest 。

反观 Node.js 侧,官方提供的 http.request(),太底层太基础了,用起来往往需要大量的封装。譬如 302 后自动跳转、文件上传、响应结果解析等等。

因此在 Node.js 社区有非常多的上层请求库封装:
  • 曾经广受社区欢迎的 request 库去年宣布停止维护后,也引起了社区比较大的混乱。。

  • Egg 内置的是 urllib,沉淀了多年在网络请求上踩的坑,足够稳定,不过代码也有点久远了。


去年 Node.js 官方推出了 undici,一个非常现代化的库,具备优越的性能,良好的扩展性,内置的 mock 等能力,集大成者。
从而 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。
目前还处于默认开启的实验性特性阶段!!!
可能是为了遵循规范, undici 的很多能力如 Mock,Proxy,Pool 等都没有提供出来。

五、五大模块

Test Runner

单元测试很重要,很多新兴的编程语言都是会内置对应的能力,但前端这块一直都是由社区来实现,前端同学耳熟能详的 Test Runner 有 MochaJest  
// 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(11);
  });

  await t.test('subtest 2', (t) => {
    assert.strictEqual(22);
  });
});

// 等价于 describe.skip() / it.skip()
test('skip option', { skiptrue }, () => {});

// 等价于 describe.only() / it.only()
test('only option', { onlytrue }, () => {});

可以看到:
  • 语法其实差不多,会更简洁一点,就一个 test(),options 除了 skip 和 only 外,还支持 concurrency 并发。
  • 无需启动器,每一个文件都是一个可执行的 Node.js 代码。
  • 暂未支持 before/after/beforeEach/afterEach 能力,看 issue 描述会后续支持。
  • 暂未支持 Reporter,但日志输出为标准 TAP 格式,所以应该很容易能复用现有的社区生态。
类似覆盖率的演进过程,以前我们需要通过 nyc 对代码转译打桩,现在变为的 Node.js 内置覆盖率输出,nyc 变为 c8 这样的覆盖率报告生成工具。
后续 mocha 等估计会变为类似的上层封装,提供批量执行 和 Reporter 等能力。

Build-time user-land snapshot

简单的说,可以把某个 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

V8 引擎升级

内置的 V8 引擎升级到 10.1 版本,值得注意的特性:
  • class fields 和 private class methods 的性能优化。
  • Intl 规范 的支持,在做日期的本地化,字符串处理的时候非常有用。
  • 数组支持 findLast() 和 findLastIndex() 等。

ESM 的支持

虽然在 18.x 中没有新的内容,但在过去的几个月中一直在持续推动 ECMAScript模块实现:
  • JSON Import Assertions 的支持。
  • JSON 模块的正式支持。
  • 对 HTTPS 和 HTTP 导入的实验性支持。
  • Node.js 加载器团队也在继续开发 ECMAScript 模块加载器实现。

工具链和编译器的升级

  • Linux 版是在 RHEL8 上构建的,要求 glibc 2.28 以上版本。

  • macOS 要求 10.15 以上版本。

  • Windows 很多旧版本也不支持了。

五、最后

关注我,一起携手进阶

欢迎关注前端早茶,与广东靓仔携手共同进阶~

浏览 49
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报