原文:15 Recent Node.js Features that Replace Popular npm Packages
多年来,Node.js 开发者一直依赖无数的 npm 包来填补平台的能力不足。从 HTTP 工具到文件系统工具,生态系统一直是 Node.js 最大的优势之一。但随着 Node.js 的不断发展,许多曾经需要第三方包的功能现在都已内置在运行时本身。
这种转变减少了依赖膨胀,提高了安全性,并使应用程序更易于维护。如果您需要一个工具来跟踪 Node.js 中第三方包的安全风险,请查看 N|Solid。
在这篇文章中,我们将介绍一些最值得注意的、可以替代流行 npm 包的 Node.js 特性。
1. node-fetch → 全局 fetch()
过去: 开发者安装 node-fetch
以便在 Node.js 中使用熟悉的浏览器 fetch()
API。
现在: 从 Node.js 18 开始,fetch()
是一个全局函数,与浏览器中的实现相同。
js
const res = await fetch('https://api.github.com/repos/nodejs/node');
const data = await res.json();
console.log(data.full_name); // "nodejs/node"
何时添加: 在 Node.js v17.5.0 中引入(实验性)
稳定化: 在 Node.js v18.0.0 中成为稳定功能
何时仍需使用 node-fetch: 仅当您需要旧版 Node.js(18 之前)的兼容性时。
2. ws (客户端) → 全局 WebSocket
过去: ws
包是 WebSocket 客户端和服务器的首选。
现在: Node.js 包含一个用于客户端连接的全局 WebSocket 类:
js
const ws = new WebSocket('wss://echo.websocket.org');
ws.onopen = () => ws.send('Hello!');
ws.onmessage = (event) => console.log('Received:', event.data);
何时添加: 在 Node.js v21.0.0 中添加了实验性的全局 WebSocket 客户端支持
稳定化: 根据目前可用的资料,仍处于实验阶段(尚未宣布稳定版本)
何时仍需使用 ws: 对于服务器端的 WebSocket 实现,ws 或基于它构建的库仍然是标准选择。
3. 测试框架 → node:test
过去: 测试需要像 mocha
、jest
或 tap
这样的库。
现在: Node.js 包含 node:test
,一个内置的测试运行器:
js
import test from 'node:test';
import assert from 'node:assert';
test('addition works', () => {
assert.strictEqual(2 + 2, 4);
});
何时添加: 在 Node.js v18.0.0 中引入(实验性)
稳定化: 从 Node.js v20.0.0 开始被视为稳定
何时仍需使用第三方框架: 如果您需要快照测试、模拟或丰富的插件生态系统等功能。请注意,node:test 对于模块来说已经足够,但对于一些较大的框架(例如全栈功能),在应用程序开发方面,第三方框架仍然有用。
4. sqlite3 / better-sqlite3 → node:sqlite [实验性]
过去: 开发者依赖像 sqlite3
或更快的 better-sqlite3
这样的原生绑定。这些需要编译,并且经常在升级时出现问题。
现在: Node.js 正在引入一个实验性的 node:sqlite
模块:
js
import { open } from 'node:sqlite';
const db = await open(':memory:');
await db.exec('CREATE TABLE users (id INTEGER, name TEXT)');
目前仍是一个实验性功能。
何时仍需使用社区包: 如果您需要高级性能调优或实验性 API 中尚未提供的功能。
5. chalk / kleur → util.styleText()
过去: 像 chalk
和 kleur
这样的库主导了控制台样式。
现在: Node.js 提供了 util.styleText()
:
js
import { styleText } from 'node:util';
console.log(styleText('red', 'Error!'));
console.log(styleText(['bold', 'green'], 'Success!'));
何时添加: 在 Node.js v20.12.0 中引入
稳定化: 在 Node.js v22.17.0 中稳定
何时仍需使用 chalk: 如果您需要丰富的主题、链式语法或向后兼容性。
6. ansi-colors / strip-ansi → util.stripVTControlCharacters()
过去: 开发者使用 strip-ansi
等包来清理日志中的转义码。
现在: Node.js 包含 util.stripVTControlCharacters():
js
import { stripVTControlCharacters } from 'node:util';
const text = '\u001B[4mUnderlined\u001B[0m';
console.log(stripVTControlCharacters(text)); // "Underlined"
优势: 原生、可靠地处理 ANSI 代码。
何时仍需使用第三方: 很少------现在大多数情况都已原生覆盖。
7. glob → fs.glob()
过去: glob
包对于文件匹配模式至关重要。
现在: Node.js 22+ 引入了 fs.glob()
:
javascript
import fs from 'node:fs/promises';
const files = await fs.glob('**/*.js');
console.log(files);
何时添加: 在 Node.js v22.0.0(或 v22 系列)中作为 fs API 扩展的一部分添加;v22.0 的发布说明包含了新的 fs glob 功能。
稳定化: 在 Node.js 22.17.0 LTS(作为 v22 发布线的一部分)中稳定。
何时仍需使用 glob: 如果您需要与旧版 Node.js 兼容。
8. rimraf → fs.rm({ recursive: true })
过去: 递归删除目录需要 rimraf
。
现在: Node.js 直接支持递归删除:
javascript
import fs from 'node:fs/promises';
await fs.rm('dist', { recursive: true, force: true });
何时添加: fs.rm()
的 recursive
选项大约从 Node.js v12.10.0 开始可用(用于旧版回调用法),在后续版本的 Promise API 中也可用;但基于 Promise 的 fs.rm()
完全支持 recursive:true, force:true
的确切补丁版本可能有所不同。官方文档显示 fs.rm(path[, options])
从 Node.js 14+ 开始包含 recursive 选项。(注意:也支持 force 选项。)
稳定化: 在所有活跃的 LTS 版本(v18, v20, v22)中已经稳定 → 不再是实验性功能。
9. mkdirp → fs.mkdir({ recursive: true })
过去: 开发者使用 mkdirp
来递归创建目录。
现在: Node.js 原生支持它:
js
await fs.mkdir('logs/app', { recursive: true });
何时添加: fs.mkdir()
的 recursive
选项在 Node.js v10.12.0 中添加。
稳定化: 自添加以来就保持稳定;它是核心 API 的一部分并被广泛使用。
10. uuid (v4) → crypto.randomUUID()
过去: 生成 UUID 意味着需要添加 uuid
包。
现在: Node.js 包含 crypto.randomUUID()
:
js
import { randomUUID } from 'node:crypto';
console.log(randomUUID());
何时添加: 在 Node.js v14.17.0 中引入
稳定化: 自引入以来就保持稳定;是 crypto 核心模块的一部分。
**11. base64-js / atob polyfills → Buffer, atob, btoa
过去: 编码/解码通常需要 polyfill。
现在: Node.js 包含 atob
和 btoa
全局变量,以及 Buffer
:
arduino
const encoded = btoa('hello');
console.log(encoded); // "aGVsbG8="
console.log(atob(encoded)); // "hello"
何时添加: atob
和 btoa
全局变量大约在 Node.js v20.0.0(或更高版本)中引入。
稳定化: 它们是当前 Node.js LTS 版本中稳定 API 的一部分。
12. url-pattern → URLPattern [实验性]
过去: 开发者依赖 url-pattern
进行路由匹配。
现在: Node.js 包含全局 URLPattern
API:
js
const pattern = new URLPattern({ pathname: '/users/:id' });
const match = pattern.exec('/users/42');
console.log(match.pathname.groups.id); // "42"
何时添加: URLPattern
在 Node.js v20.0.0 中作为实验性功能添加。
稳定化: 截至目前,在 Node.js 文档中仍标记为实验性(尚未稳定)。
13. dotenv (基础功能) → --env-file 标志 [实验性]
过去: 加载 .env
文件需要 dotenv
。
现在: Node.js 可以直接加载 env 文件:
ini
node --env-file=.env app.js
何时添加: --env-file
标志在 Node.js v20.10.0 中引入(实验性)。
稳定化: 尚未稳定;仍处于实验阶段。
何时仍需使用 dotenv: 如果您需要高级功能,如变量扩展或多个 env 文件。
14. event-target-shim → EventTarget
过去: Node.js 有自己的 EventEmitter
,开发者使用 event-target-shim
来获得符合 Web 标准的 EventTarget
。
现在: EventTarget
全局可用:
js
const target = new EventTarget();
target.addEventListener('ping', () => console.log('pong'));
target.dispatchEvent(new Event('ping'));
何时添加: 在 Node.js v15.0.0 中引入
稳定化: 在 Node.js v15.4.0 中稳定,当时在全局变量文档中被标记为"不再实验"。
15. tsc (基础转译) → Node.js 实验性 TypeScript 支持
过去: 运行 .ts
文件需要完整的 TypeScript 工具链(tsc
或 ts-node
)。
现在: Node.js 包含实验性的 TypeScript 支持:
css
node --experimental-strip-types app.ts
何时添加: 此功能非常新;"--strip-types" 实验性标志在 Node.js v21.0.0 左右或该主要版本中引入。官方文档显示在 21.x 发布线中的实验性支持。(确切的次要/补丁版本在我找到的资料中没有完全记载。)
稳定化: 尚未稳定 --- 仍处于实验阶段。
何时仍需使用 tsc: 用于完整的类型检查、声明文件和生产级构建。
最终想法
Node.js 的演变显示出一个明显的趋势:曾经需要外部依赖的功能现在已成为核心的一等公民。这种转变有助于开发者:
- 减少依赖开销。
- 最小化供应链和安全风险。
- 编写更能跨浏览器和服务器移植的代码。
但是,跟上这些变化并不总是那么容易,尤其是在生产环境中,稳定性、性能和安全性至关重要。这就是 N|Solid 的用武之地。
N|Solid 为您提供对 Node.js 应用程序的深度洞察,因此您可以准确查看像 fetch
、node:test
或 crypto.randomUUID()
这样的内置功能在真实工作负载下的表现。借助我们的 AI 驱动代理 N|Sentinel,您可以监控使用情况,并获得优化建议甚至代码级解决方案。
如果您正在现代化您的技术栈并利用这些内置的 Node.js 功能,在 N|Solid 上运行可以确保您能够充满信心地、以可扩展的性能和安全性来实现这一目标。