← 返回文章列表
Node.js·179 次阅读

Node.js 22/23 新特性盘点:原生技能树又点亮了不少

年初把服务器的 Node 从 18 升到了 22 LTS。升级过程中把这两个版本的 changelog 完整翻了一遍,发现不少"以前要装包,现在原生就有"的特性。挑值得关注的整理一篇。

require() 可以加载 ESM 了

CommonJS 和 ESM 双轨制折磨了社区五年。Node 22 迈出了历史性的一步:

// 以前:CJS 里 require ESM 模块直接报错
// ERR_REQUIRE_ESM: require() of ES Module ... not supported

// Node 22:可以了!(模块里没有顶级 await 的前提下)
const lodash = require('lodash-es')

对库作者意义更大:以后可以只发 ESM 一份产物,CJS 用户也能用。双构建(.cjs + .mjs)的时代终于看到了终结的曙光。

内置 WebSocket 客户端

以前 Node 里连 WebSocket 要装 ws 库,现在原生全局可用,API 和浏览器一致:

// 不用 npm install ws
const socket = new WebSocket('wss://example.com/feed')

socket.addEventListener('open', () => {
  socket.send(JSON.stringify({ type: 'subscribe', channel: 'prices' }))
})

socket.addEventListener('message', (event) => {
  console.log('收到:', JSON.parse(event.data))
})

注意这是客户端能力。做 WebSocket 服务端还是要用 ws 库。对写实时数据订阅脚本、跨服务推送的消费者来说,少一个依赖。

内置 SQLite:node:sqlite

Node 22.5 加入的实验性内置数据库:

const { DatabaseSync } = require('node:sqlite')

const db = new DatabaseSync(':memory:')

db.exec(`
  CREATE TABLE todos (
    id INTEGER PRIMARY KEY,
    title TEXT NOT NULL,
    done INTEGER DEFAULT 0
  )
``)

const insert = db.prepare('INSERT INTO todos (title) VALUES (?)')
insert.run('写一篇 Node 22 盘点')

const rows = db.prepare('SELECT * FROM todos').all()
console.log(rows) // [ { id: 1, title: '写一篇 Node 22 盘点', done: 0 } ]

写 CLI 工具、本地脚本、单元测试需要个轻量存储时,不用再装 sqlite3(那个原生编译的坑装过的人都懂)。目前还是实验特性(要 --experimental-sqlite),生产慎用,但方向很明确。

其他实用更新速览

glob 原生支持(fs.glob,22.0):

const { glob } = require('node:fs/promises')

// 以前要装 glob 或 fast-glob
for await (const file of glob('src/**/*.test.js')) {
  console.log(file)
}

ArrayBuffer 转移与更多 V8 新语法:Node 22 内置 V8 12.4,Array.fromAsync、Object.groupBy、Promise.withResolvers 全都稳定可用:

// Promise.withResolvers:在外部控制 promise 的 resolve/reject
const { promise, resolve, reject } = Promise.withResolvers()

setTimeout(() => resolve('搞定'), 1000)
await promise
// Object.groupBy:按条件分组,以前靠 lodash
const todos = [
  { title: '写文', done: true },
  { title: '健身', done: false },
  { title: '读书', done: true },
]

Object.groupBy(todos, (t) => (t.done ? 'done' : 'pending'))
// { done: [...], pending: [...] }

watch 模式稳定(22.0):node --watch server.js 文件变化自动重启,开发小项目连 nodemon 都省了。配合之前版本的 --env-file、--test(内置测试 runner),Node 的"原生技能树"越来越全。

Node 23 的非 LTS 尝鲜

23 是奇数版本(不会转 LTS),主要是给 24 预演:

  • require(esm) 默认开启(22 里要 flag)
  • 移除了 32 位 Windows 支持等历史包袱

生产环境别追奇数版,等今年 10 月的 Node 24 LTS 即可。

升级建议

  • 生产项目:18 → 22 LTS,别跳奇数版
  • 升级前跑一遍测试,重点查原生模块(bcrypt、sharp 这类要重新编译)
  • 本地开发可以开始用 --watch 和原生 --env-file 替代 nodemon + dotenv
  • 库里还在双构建的作者,可以关注 require(esm) 的普及度,时机成熟就砍 CJS 产物

小结

  • require 加载 ESM 是历史性和解,双构建时代进入倒计时
  • 原生 WebSocket 客户端、内置 SQLite、fs.glob,三个"少装一个包"
  • Promise.withResolvers、Object.groupBy 等 V8 新语法已稳定
  • 生产升 22 LTS,奇数版只用来尝鲜

Node 这几年的方向很清晰:把社区验证过的刚需能力一个个收编进原生。对开发者来说,最直观的好处就是 package.json 越来越短了。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4