
大家好,我是 Immerse,一名独立开发者、内容创作者、AGI实践者。
https://yaolifeng.com 也同步更新。我会在这里分享关于编程、独立开发、AI、出海、个人思考等内容。
如果本文对你有帮助,欢迎动动小手指一键三连(点赞、评论、转发),给我一些支持和鼓励,谢谢!
之前装个 Node.js 项目,npm 包能装一大堆。
现在发现很多包其实不用装了,Node.js 自己就支持。
这次整理了 15 个已经被 Node.js 原生功能替代的热门 npm 包。
有些已经稳定了,有些还在实验阶段,但都能用起来了。
以前在 Node.js 里用 fetch,必须装 node-fetch。
现在 Node.js 18 开始,fetch 已经是全局函数了,和浏览器里的用法完全一样。
const res = await fetch("https://api.github.com/repos/nodejs/node");
const data = await res.json();
console.log(data.full_name);
直接就能用,不用装任何包。
Node.js 17.5 开始实验性支持,到 18 就稳定了。
如果你的项目还在用 Node.js 18 之前的版本,那还是得装 node-fetch。
之前做 WebSocket 客户端,基本都用 ws 这个包。
现在 Node.js 有了全局的 WebSocket 类。
const ws = new WebSocket("wss://echo.websocket.org");
ws.onopen = () => ws.send("Hello!");
ws.onmessage = (event) => console.log("Received:", event.data);
Node.js 21 加的,不过还是实验性的。
要注意的是,这只是客户端支持。
如果要做 WebSocket 服务端,还是得用 ws 或者其他库。
以前写测试,要装 mocha、jest 这些框架。
现在 Node.js 自带测试模块 node:test。
import test from "node:test";
import assert from "node:assert";
test("addition works", () => {
assert.strictEqual(2 + 2, 4);
});
Node.js 18 加的实验性功能,到 20 就稳定了。
如果需要快照测试、mock 这些高级功能,第三方框架还是更强。
不过对于模块级别的测试,node:test 完全够用了。
之前用 SQLite,要装 sqlite3 或 better-sqlite3。
这俩包都需要编译原生模块,升级 Node.js 版本经常出问题。
现在 Node.js 在开发 node:sqlite 模块。
import { open } from "node:sqlite";
const db = await open(":memory:");
await db.exec("CREATE TABLE users (id INTEGER, name TEXT)");
不过还是实验性的,等稳定了就能彻底告别编译问题了。
给控制台输出加颜色,以前都用 chalk 或 kleur。
现在 Node.js 有 util.styleText 函数。
import { styleText } from "node:util";
console.log(styleText("red", "Error!"));
console.log(styleText(["bold", "green"], "Success!"));
Node.js 20.12 加的,到 22.17 就稳定了。
如果需要复杂的主题配置或链式调用,chalk 还是更好用。
但简单的颜色输出,原生的就够了。
以前要去掉日志里的 ANSI 转义码,得装 strip-ansi。
现在有 util.stripVTControlCharacters 函数。
import { stripVTControlCharacters } from "node:util";
const text = "\u001B[4mUnderlined\u001B[0m";
console.log(stripVTControlCharacters(text));
原生处理,稳定可靠。
基本不需要再装第三方包了。
匹配文件路径,以前必须用 glob 包。
Node.js 22 开始有 fs.glob 函数了。
import fs from "node:fs/promises";
const files = await fs.glob("**/*.js");
console.log(files);
22 版本就稳定了,可以放心用。
老项目还在用旧版本 Node.js 的话,还是得继续用 glob 包。
删除整个目录树,以前都用 rimraf。
现在 fs.rm 直接支持递归删除。
import fs from "node:fs/promises";
await fs.rm("dist", { recursive: true, force: true });
Node.js 12.10 就有了,现在所有 LTS 版本都稳定支持。
创建多级目录,以前要装 mkdir。
现在 fs.mkdir 原生支持。
await fs.mkdir("logs/app", { recursive: true });
Node.js 10.12 就加了,早就稳定了。
生成 UUID v4,以前要装 uuid 包。
现在 crypto 模块自带 randomUUID 函数。
import { randomUUID } from "node:crypto";
console.log(randomUUID());
Node.js 14.17 就有了,稳定版本。
以前要 polyfill atob 和 btoa 函数。
现在这俩已经是全局函数了。
const encoded = btoa("hello");
console.log(encoded);
console.log(atob(encoded));
Buffer 一直都有,现在加上 atob 和 btoa,浏览器和 Node.js 的代码终于统一了。
Node.js 20 左右加的,现在 LTS 版本都有。
做路由匹配,以前要装 url-pattern。
现在有全局的 URLPattern API。
const pattern = new URLPattern({ pathname: "/users/:id" });
const match = pattern.exec("/users/42");
console.log(match.pathname.groups.id);
Node.js 20 加的,不过还是实验性的。
但已经能用了,而且和浏览器的 URLPattern 完全一样。
之前加载环境变量文件,必须装 dotenv。
现在可以用 --env-file 参数。
node --env-file=.env app.js
Node.js 20.10 加的实验性功能。
如果需要变量展开或多文件支持,dotenv 还是更强。
但简单场景下,原生的就够了。
以前 Node.js 只有 EventEmitter,要用 Web 标准的 EventTarget 得装 event-target-shim。
现在 EventTarget 已经是全局的了。
const target = new EventTarget();
target.addEventListener("ping", () => console.log("pong"));
target.dispatchEvent(new Event("ping"));
Node.js 15 加的,15.4 就稳定了。
浏览器和 Node.js 终于可以用同样的事件 API 了。
以前运行 .ts 文件,要装 TypeScript 编译器或 ts-node。
现在 Node.js 有实验性的 TypeScript 支持。
node --experimental-strip-types app.ts
Node.js 21 加的实验性功能。
不过这只是去掉类型标注,不做类型检查。
生产环境还是得用完整的 TypeScript 工具链。
看这些变化,能发现一个趋势。
以前需要外部依赖的功能,现在越来越多变成了核心功能。
这样做有几个好处。
减少依赖数量,项目更轻量。
降低供应链攻击风险,不用担心某个包被投毒。
代码在浏览器和服务端之间更容易移植。
这些原生功能,浏览器支持好的就可以直接用了。
实验性的功能可以在开发环境先试试。