五个可替代 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 --test 或 node --test --watch 以自动重新运行。
何时保留 Jest: 快照测试、广泛的 mock 工具或代码覆盖率报告需求。
Discover how at OpenReplay.com.
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.