狼叔直播 Reaction《学习指北:Node.js 2022 全解析》

大家好,我是若川。持续组织了6个月源码共读活动,感兴趣的可以点此加我微信 ruochuan02 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列

本文是狼叔在 2 月 16 日在掘金直播《学习指北:Node.js 2022 全解析》的 Reaction,狼叔的直播干货很多,本文尽量保证原内容的同时,额外加入了一些相关资料和链接,方便你学习。

Node.js 2021

  • Node 2021 开发者报告链接[1]

Node 2021 开发者报告解析

Node.js 好像不是很火了?其实不然。

从 Node.js 源码更新内容来看,Node.js 正在健康平稳的发展、从可用到好用在转变,在易用性上有很大提升。性能的牌打完了,开始打“用户体验”的牌。

核心产出 async_hooks、profiling、tracing、dump debug、report 等。让开发者能以更低的门槛提升 Node.js 应用的开发体验。

1.开发框架变化较大,造轮子变少,TS 变多,使用企业级框架变多

ff258a5a70eb1209b5f2c1d885ffb194.png c69313d9f46f16951e4cb47cc67de667.png

Egg.js 在国内使用普及率很高,而 Midway 和 Nest 增长较快,和 TypeScript 普及有一定关系。

2.版本更新变化较大,升级比较积极

ffc317ae251fd9271960ecc0d3aac220.png

去年主要是使用 Node12,2021 年 Node14 占比将近一半,更新还是较快的。

(如果你想优化性能,最好的办法就是升级 Node 版本 :))

3.吐糟变多,意味着用的人变多,趋于成熟

389b5c10d37c680ec087e8ab47fd9b30.png

“世界上只有两种语言,一种是没有人用的语言,一种是被抱怨的语言。”

4.出圈:年龄分布较去年比变大,使用工种也变得比较丰富

c68fb6b749918974c8d18f21fc1aef4f.png

整个 Node 社区不再只是围绕前端工程师去做,后端、全栈工程师、架构师甚至运维、技术总监都有一定的接触,在校生和实习生也有一定的使用量。

5.使用困惑:性能优化,内存泄漏以及 npm 依赖

34703378a8ed53698ae0689c2769f5e4.png

6.未来:从业经验越高则越关注性能和 Serverless

fef704ccae731ce27e22d849ead0a44e.png
  • 从业经验越高则越关注 WebAssembly (WASI) 和 N-API。

  • 越年轻的同学越关注 Serverless。

好东西里藏着的趋势

1.clipanion

  • clipanion 仓库链接[2]

class FooCommand extends Command {
    static paths = [[`foo`]];
    async execute() {
        this.context.stdout.write(`Foo\n`);
    }
}

class BarCommand extends Command {
    static paths = [[`bar`]];
    async execute() {
        this.context.stdout.write(`Bar\n`);
    }
}

TS + 面向对象 + 模板模式十分优雅。

clipanion 是一个没有运行时依赖的类型安全 CLI 库。Yarn v2 版本[3] berry 源码中用到了它。包括 Node.js 中新增的 Corepack(包管理器的管理器,用来管理 npm、yarn、pnpm、cnpm等) 也采用了它。

可以看出社区对它的看重,虽然它的 Star 数不高,但还是十分值得学习的。

对比一下常见的 CLI 库 Commander.js[4] 和 cac[5],它们的写法是函数式的,通过定义一个函数,使用 option 传入参数。

看你喜欢哪种写法,它们都是不错的选择。

// Commander.js
const { program } = require('commander');

program
  .option('--first')
  .option('-s, --separator <char>');

program.parse();

const options = program.opts();
const limit = options.first ? 1 : undefined;
console.log(program.args[0].split(options.separator, limit));
// examples/basic-usage.js
const cli = require('cac')()

cli.option('--type <type>', 'Choose a project type', {
  default: 'node',
})

const parsed = cli.parse()

console.log(JSON.stringify(parsed, null, 2))

2.TS 相关的 10 个项目推荐

  • CLI 模块:clipanion[6]

  • 测试模块:uvu[7]

  • Web 模块(express 替代品):tinyhttp[8]

  • 数据库模块:typeorm[9]

  • Web 应用:midway[10]、daruk[11]、loopback[12]、nest[13]、ssr[14]

  • react 全家桶:umi[15]

2.1 find-my-way

  • find-my-way[16]

const http = require('http')
const router = require('find-my-way')()

router.on('GET', '/', (req, res, params) => {
  res.end('{"message":"hello world"}')
})

const server = http.createServer((req, res) => {
  router.lookup(req, res)
})

server.listen(3000, err => {
  if (err) throw err
  console.log('Server listening on: http://localhost:3000')
})

受 Go 语言中 echo 框架的路由实现所启发,具体实现基于基数树[17]。部分代码从 trekjs[18]提取。

性能

基准测试 all together 中 find-my-way 是 525,798 ops/sec,koa-router 是 161,220 ops/sec。每秒能够处理的请求数差距还是非常明显的,基数树的这种方式远远比正则快的多。

=======================
 find-my-way benchmark
=======================
short static: 10,102,066 ops/sec
static with same radix: 3,887,679 ops/sec
dynamic route: 1,637,929 ops/sec
mixed static dynamic: 2,289,554 ops/sec
long static: 5,403,719 ops/sec
wildcard: 3,037,119 ops/sec
all together: 525,798 ops/sec

======================
 koa-router benchmark
======================
short static: 1,004,122 ops/sec
static with same radix: 1,029,369 ops/sec
dynamic route: 1,015,635 ops/sec
mixed static dynamic: 968,784 ops/sec
long static: 1,027,857 ops/sec
wildcard: 1,033,432 ops/sec
all together: 161,220 ops/sec

下图来自于 Fasify 的基准测试[19]

60b32727141b8db53c504785e3513bb2.png

Fastify 和 Restify 都是基于 find-my-way 实现的路由,Restify 早期版本基于 express 的路由,Fastify 能处理的每秒请求数比原生的还高。从数据结构角度来进行优化是未来提升性能比较重要的一点。

  • Radix Tree 原理[20]

  • path-to-regexp[21]

2.2 性能优化的 4 个建议

a10c739469ae495090ed4382dc122830.png
  • fast-json-stringify[22]

2.3 测试框架演进

feefff2d06345e2785cc7767326a10eb.png

idea

造轮子:把 junit 的 API 搬进 TS。

6d7fa16b911b841ccc9a4e19196e2e79.png

实现路径

930242dc3ae2a38bb7ae29d9781e43cc.png

ts-import vs typescript-require

b58f452add833389a16344f359f1f379.png

这二者的性能还是差一些,后面准备用 Rust 或者 Go 的编译器重写。

xv

在造轮子的过程中,发现了一个有意思的库 xv。作者还有 json-server、lowdb 等作品。

源码只有 40 几行,无需定义任何测试语法。

  • https://github.com/typicode/xv[23]

uvu

uvu[24] 的源码值的学习。

d19a81c31c6566f0118628f03b9f3e6c.png

常见的 Node 测试框架:

  • ava[25]

  • jest[26]

  • mocha[27]

  • tape[28]

  • uvu[29]

vitest

会替代掉 jest,也会越来越流行。

  • vitest[30]

94b9e9e8db8659130f54bcbc310994dc.png

2.4 easy-monitor

69f7fcdc80f89f289b388021216a2aff.png
  • easy-monitor[31] 是近年来性能监控的最好方案。

监控痛点

7a0929f4618bcea16aa75dd6048851fd.png

一些痛点对开发者门槛要求比较高,但是 easy-monitor 已经帮我们做好了。

  1. 性能调优,永不过时

  2. 基于 addon,没有版本依赖。各种内存泄漏分析工具与 Coredump 分析工具,绝对有你的知识盲点

  3. 对阅读 node 源码和深入理解服务器有非常大的帮助

  4. 对理解 libuv,以及 c++ 也有帮助

  5. 源码基于 egg 和 vue,都是非常成熟的技术

  6. 作者一定要靠谱

完善的应用故障定位步骤

398e846c8c60475620eeaac69c0cc066.png

2.5 rushstack

f9a9a829e24b53e7579fbb5f2816ce3a.png

Turborepo 对于 Lerna 是竞品,而目前还对标不上 rushstack[32],rushstack 适用于超大型项目。微软的全系列产品也都在使用 rushstack 全家桶。在未来有超大型项目挑战的时候 rushstack 是一个非常好的实践借鉴。

db89bb561b48eeb4f11360caa57f13ac.png 9803ef420b8732c44c3fc9667b28c1cb.png

总结

93cb2c480b8ecd5f8561a2a1c7353d8f.png

八大类 Web 框架

00d0eeb985dbe31a6b8f7e20d3bf26a0.png 8452e6bc22d72c249d5a13e760d1eb91.png
  • Jamstack,下一代 Web 建站技术栈?[33]

架构演进

这一趴主要引用了 Node 地下铁的一次分享,原文链接如下。

  • JavaScript 全栈⾼效研发在语雀中的实践[34]

前端 3.0

6e30b19a7bddd83206a395305fcbf11f.png

重新思考前后端的关系

BFF vs FFB

前端代码里的胶水代码太多了,本质上讲,从数据库到 API 字段,然后到前端渲染,应该是一个非常纯净的过程。但是由于业务发展或者是各种情况,数据库里面的字段不能拿出来直接用,前后端的沟通成本又导致了中间加了额外的各种逻辑。这就导致了前端的复杂度一直在上升。

  • 更多内容可以参考狼叔在社区中的回答[35]

97a753e56890b019f068cb7c877397e5.png

参考资料

[1]

Node 2021 开发者报告链接: https://nodersurvey.github.io/reporters/

[2]

clipanion 仓库链接: https://github.com/arcanis/clipanion

[3]

Yarn v2 版本: https://github.com/yarnpkg/berry

[4]

Commander.js: https://www.npmjs.com/package/commander

[5]

cac: https://github.com/cacjs/cac

[6]

clipanion: https://github.com/arcanis/clipanion

[7]

uvu: https://github.com/lukeed/uvu

[8]

tinyhttp: https://github.com/tinyhttp/tinyhttp

[9]

typeorm: https://github.com/typeorm/typeorm

[10]

midway: https://github.com/midwayjs/midway

[11]

daruk: https://github.com/darukjs/daruk

[12]

loopback: https://github.com/strongloop/loopback

[13]

nest: https://github.com/nestjs/nest

[14]

ssr: https://github.com/ykfe/ssr

[15]

umi: https://github.com/umijs/umi

[16]

find-my-way: https://github.com/delvedor/find-my-way

[17]

基数树: https://en.wikipedia.org/wiki/Radix_tree

[18]

trekjs: https://github.com/trekjs/trek

[19]

Fasify 的基准测试: https://github.com/fastify/fastify/blob/main/README.md#benchmarks

[20]

Radix Tree 原理: https://ivanzz1001.github.io/records/post/data-structure/2018/11/18/ds-radix-tree

[21]

path-to-regexp: https://github.com/pillarjs/path-to-regexp

[22]

fast-json-stringify: https://github.com/fastify/fast-json-stringify

[23]

https://github.com/typicode/xv: https://github.com/typicode/xv

[24]

uvu: https://github.com/lukeed/uvu/blob/master/src/index.js

[25]

ava: https://github.com/avajs/ava

[26]

jest: https://github.com/facebook/jest

[27]

mocha: https://github.com/mochajs/mocha

[28]

tape: https://github.com/substack/tape

[29]

uvu: https://github.com/lukeed/uvu

[30]

vitest: https://github.com/vitest-dev/vitest

[31]

easy-monitor: https://github.com/hyj1991/easy-monitor

[32]

rushstack: https://github.com/microsoft/rushstack

[33]

Jamstack,下一代 Web 建站技术栈?: https://zhuanlan.zhihu.com/p/281085404

[34]

JavaScript 全栈⾼效研发在语雀中的实践: https://www.yuque.com/summ/colacake/js_fullstack

[35]

更多内容可以参考狼叔在社区中的回答: https://www.zhihu.com/question/493891614/answer/2264072484

4bee77ca048661a4be7ed10ac27c64a4.gif

················· 若川简介 ·················

你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》20余篇,在知乎、掘金收获超百万阅读。
从2014年起,每年都会写一篇年度总结,已经写了7篇,点击查看年度总结
同时,最近组织了源码共读活动,帮助3000+前端人学会看源码。公众号愿景:帮助5年内前端人走向前列。

c33a956690b66b83ea4448808c79c34d.png

识别方二维码加我微信、拉你进源码共读

今日话题

略。分享、收藏、点赞、在看我的文章就是对我最大的支持~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值