Back

五个可替代 npm 包的 Node.js 内置 API

五个可替代 npm 包的 Node.js 内置 API

如果你仍在为基本的 HTTP 请求、文件操作或测试安装 npm 包,那么你正在为 Node.js 项目添加不必要的依赖。现代 Node.js(v20+)包含了强大的内置 API,可以消除对许多流行包的需求,从而减少打包体积、提高安全性并简化维护工作。

让我们探讨五个可以替代你现在可能正在使用的 npm 包的核心 Node.js 内置 API,并通过实际示例展示如何进行迁移。

核心要点

  • 自 Node.js 18 起,原生 fetch API 无需外部依赖即可处理大多数 HTTP 请求
  • 内置测试运行器为简单应用提供零依赖的测试解决方案
  • 现代 fs 方法原生支持递归操作和模式匹配
  • crypto.randomUUID() 无需额外包即可生成安全的 UUID
  • WebSocket 客户端支持原生可用(Node.js 21+ 中为实验性功能)

1. 全局 fetch() 替代 axios 和 node-fetch

自 Node.js 18 稳定以来,原生 fetch API 无需外部依赖即可处理大多数 HTTP 请求。虽然像 axios 这样的包提供了拦截器和自动重试等便利功能,但 fetch() 涵盖了大多数使用场景。

之前(使用 axios):

const axios = require('axios');
const response = await axios.get('https://api.github.com/users/nodejs');
console.log(response.data);

之后(原生 fetch):

const response = await fetch('https://api.github.com/users/nodejs');
const data = await response.json();
console.log(data);

对于超时控制,使用 AbortController:

const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
const response = await fetch(url, { signal: controller.signal });

何时保留 axios: 复杂的拦截器链、进度跟踪或自动请求重试。

2. node:test 运行器替代 Jest 和 Mocha

内置测试运行器(在 Node.js 20+ 中稳定并推荐使用)提供了一个零依赖的测试解决方案,非常适合库和简单应用。

之前(使用 Jest):

// 需要安装和配置 jest
describe('Math operations', () => {
  test('adds numbers', () => {
    expect(2 + 2).toBe(4);
  });
});

之后(原生 node:test):

import { test } from 'node:test';
import assert from 'node:assert';

test('adds numbers', () => {
  assert.strictEqual(2 + 2, 4);
});

运行测试:node --testnode --test --watch 以自动重新运行。

何时保留 Jest: 快照测试、广泛的 mock 工具或代码覆盖率报告需求。

3. 文件系统辅助功能替代 rimraf、mkdirp 和 glob

现代 fs 方法原生支持递归操作和模式匹配。

之前(多个包):

const rimraf = require('rimraf');
const mkdirp = require('mkdirp');
const glob = require('glob');

await rimraf('dist');
await mkdirp('dist/assets');
const files = await glob('src/**/*.js');

之后(原生 fs):

import { rm, mkdir } from 'node:fs/promises';
import { glob } from 'node:fs';

await rm('dist', { recursive: true, force: true });
await mkdir('dist/assets', { recursive: true });

// 注意:glob() 需要 Node.js 22+
for await (const file of glob('src/**/*.js')) {
  console.log(file);
}

这些原生 Node.js 功能以相同的功能消除了三个依赖项。

4. crypto.randomUUID() 替代 uuid 包

无需 uuid 包(每周下载量 1.61 亿)即可生成加密安全的 UUID。

之前:

const { v4: uuidv4 } = require('uuid');
const id = uuidv4();

之后:

import { randomUUID } from 'node:crypto';
const id = randomUUID();

此内置 API 生成符合 RFC-4122 版本 4 的 UUID,具有与 uuid 包相同的安全保证。

何时保留 uuid: 生成非 v4 版本的 UUID(v1、v3、v5)。

5. WebSocket 客户端替代 ws 包

Node.js 包含全局 WebSocket 客户端(在 Node.js 22+ 中稳定)。它适用于客户端使用,但服务器端 WebSocket 支持仍需要像 ws 这样的包。

之前(使用 ws):

const WebSocket = require('ws');
const ws = new WebSocket('wss://echo.websocket.org');
ws.on('open', () => ws.send('Hello'));

之后(原生 WebSocket):

const ws = new WebSocket('wss://echo.websocket.org');
ws.onopen = () => ws.send('Hello');
ws.onmessage = (event) => console.log(event.data);

何时保留 ws: 服务器端 WebSocket 实现或在 API 稳定之前的生产环境使用。

进行迁移:实际考虑因素

在用原生 API 替换 npm 包之前,请考虑:

  • Node.js 版本要求:确保你的生产环境运行 Node.js 20+(理想情况下是 22 LTS)
  • 功能对等性:原生 API 可能缺少高级功能(axios 拦截器、Jest 快照)
  • 团队熟悉度:考虑不同 API 的学习曲线

从替换简单的工具开始,如 randomUUID() 和文件系统操作。这些能以最小的风险提供即时收益。对于更复杂的替换,如测试框架或 HTTP 客户端,请评估原生功能是否满足你的特定需求。

结论

这五个 Node.js 内置 API 展示了该平台如何演进以减少对外部包的依赖。通过利用原生 fetch、node:test、现代 fs 方法、crypto 工具和 WebSocket 支持,你可以显著减少项目的依赖占用,同时保持甚至改进功能。

关键是要知道何时原生 API 足够,何时专用的 npm 包仍能提供价值。从小处着手,彻底测试,并在适合你的用例时逐步迁移到原生解决方案。

常见问题

大多数功能需要 Node.js 18 或更新版本。fetch API 需要 v18+,node:test 需要 v20+,glob 需要 v22+。在从 npm 包迁移之前,请检查生产环境的 Node.js 版本。

如果你谨慎迁移就不会。原生 API 与 npm 包的语法不同。在开发环境中彻底测试,更新代码以匹配新的 API 模式,并考虑为原生 API 不支持的高级功能保留包。

原生 API 通常由于 C++ 实现和无抽象开销而性能更好。但是,专用包可能会更好地优化特定用例。对实际工作负载进行基准测试,以便对性能关键代码做出明智的决策。

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay