Node.js 24 正式进入 LTS:这些变化直接影响你的日常开发

2026-05-21 27 预计阅读时间:1 分钟
来源:nodejs.org AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:7 分钟

Node.js 24.16.0 标志着 24.x 分支正式进入长期支持阶段。相比仍在维护期的 22.x LTS,24 带来了一批从实验走向稳定的能力——其中几项会直接改变你写代码的方式。

require() 终于能加载 ESM 包了

过去几年,CJS 和 ESM 的互操作一直是 Node.js 最大的痛点之一。你在 CJS 项目里 require('some-esm-only-package'),直接报错。24.x 中 require(esm) 从实验特性变为正式支持——同步加载 ESM 模块不再需要 --experimental-require-module 标志。

这意味着:大量只提供 ESM 导出的第三方包,现在可以在老项目里直接引用,不需要绕道动态 import() 或改整个项目为 ESM。

// 在 CJS 文件中直接 require 一个纯 ESM 包
const { format } = require('date-fns'); // date-fns v3 是 ESM-only

console.log(format(new Date(), 'yyyy-MM-dd'));

需要注意的限制:被 require 的 ESM 模块不能包含顶层 await,否则仍会抛出 ERR_REQUIRE_ASYNC_MODULE。对于绝大多数工具库这不是问题,但涉及异步初始化的包仍需动态 import()

内置 WebSocket 客户端:不再强制依赖 ws

Node.js 22 实验性引入了原生 WebSocket 客户端,24.x 中 API 进一步稳定。日常场景下,你不再需要为每个项目安装 wswebsocket 包。

import { WebSocket } from 'node:websocket';

const ws = new WebSocket('wss://echo.websocket.org');

ws.addEventListener('open', () => {
  ws.send('hello from native WebSocket');
});

ws.addEventListener('message', (event) => {
  console.log('收到回显:', event.data);
  ws.close();
});

ws.addEventListener('error', (err) => {
  console.error('连接出错:', err.message);
});

当前原生 WebSocket 仅支持客户端角色,不提供服务端实现。如果你需要搭建 WS 服务器,ws 包仍然是首选。但对于消费外部 WS API 的场景——比如实时行情推送、日志流——原生模块足够且零依赖。

node:sqlite 模块:本地数据库不再需要第三方绑定

24.x 继续推进 node:sqlite 模块的稳定化。它基于 SQLite 3 的 WASM 构建,无需编译原生绑定,跨平台行为一致。

import { DatabaseSync } from 'node:sqlite';

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

db.exec(`
  CREATE TABLE kv (key TEXT PRIMARY KEY, value TEXT);
  INSERT INTO kv VALUES ('config', '{"theme":"dark"}');
`);

const row = db.prepare('SELECT value FROM kv WHERE key = ?').get('config');
console.log(row); // { value: '{"theme":"dark"}' }

db.close();

DatabaseSync 是同步接口,适合脚本、CLI 工具、小规模配置存储等不需要高并发的场景。异步版本 Database 也在推进中。对于需要并发访问的 Web 服务端,仍建议使用 better-sqlite3bun:sqlite 等成熟方案,等异步 API 稳定后再切换。

测试运行器增强:覆盖率与 mock 更实用

node:test 在 24 中进一步补全能力:

  • --experimental-test-coverage 标志现在输出行级和分支级覆盖率,格式接近 Istanbul,可被 CI 工具消费。
  • mock.fn() 支持更灵活的恢复策略,mock.restore() 可按单个 mock 恢复而非全局重置。
import { describe, it, mock } from 'node:test';
import assert from 'node:assert/strict';

function fetchUser(id) {
  return { id, name: 'Alice' };
}

describe('用户模块', () => {
  it('应返回正确用户', () => {
    const fn = mock.fn(fetchUser);
    fn(42);
    assert.equal(fn.mock.calls.length, 1);
    assert.deepEqual(fn.mock.calls[0].arguments, [42]);
    mock.restore(fn); // 只恢复这一个 mock
  });
});

运行测试并生成覆盖率:

node --experimental-test-coverage --test test/*.test.js

如果你目前用 Jest,迁移成本仍然不小(Jest 的 snapshot、自定义 runner 等功能 Node 原生测试器还不覆盖)。但对于新项目或纯逻辑测试场景,原生方案足够且启动速度快一个数量级。

升级前的实操检查清单

24.x 进入 LTS 是采用信号,但升级不是无风险的。建议按以下步骤推进:

# 1. 用 nvm 或 fnm 安装 24 LTS
nvm install 24
nvm use 24

# 2. 检查项目依赖兼容性
npm ls --omit=dev          # 列出生产依赖
node -e "require('your-critical-package')"  # 快速验证核心包能否加载

# 3. 运行现有测试
npm test

# 4. 检查是否用了已移除的 API
#    24 移除了部分 22 中已废弃的 API(如部分 fs 同步方法的旧签名)
#    查看完整变更:https://nodejs.org/en/blog/release/v24.0.0

需要特别留意的风险点:

  • require(esm) 对顶层 await 的 ESM 包仍不支持,确认你的依赖没有这种情况。
  • 原生 WebSocket 是客户端-only,别误删服务端依赖的 ws
  • node:sqlite 的同步 API 在高并发下会阻塞事件循环,Web 服务端慎用。
  • 如果项目用了 node:test 的实验性子集(如 snapshot),确认 24 中对应 API 是否已稳定或签名有变。

24.x LTS 的维护窗口将持续到 2027 年 4 月。对于新项目,直接用 24 是合理选择;对于在 22.x 上稳定运行的项目,建议先在 CI 中并行跑 24 测试,确认无阻断问题后再切换生产环境。


相关推荐