大家好,我是 Immerse,一名独立开发者、内容创作者、AGI 实践者。
关注公众号:沉浸式趣谈,获取最新文章(更多内容只在公众号更新)
个人网站:https://yaolifeng.com 也同步更新。
转载请在文章开头注明出处和版权信息。
我会在这里分享关于编程、独立开发、AI干货、开源、个人思考等内容。
如果本文对您有所帮助,欢迎动动小手指一键三连(点赞、评论、转发),给我一些支持和鼓励,谢谢!
之前装个 Node.js 项目,npm 包能装一大堆。
现在发现很多包其实不用装了,Node.js 自己就支持。
这次整理了 15 个已经被 Node.js 原生功能替代的热门 npm 包。
有些已经稳定了,有些还在实验阶段,但都能用起来了。
fetch 终于成全局函数了
以前在 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 也原生支持了
之前做 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 也要原生支持了
之前用 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 了
给控制台输出加颜色,以前都用 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 码也不用装包了
以前要去掉日志里的 ANSI 转义码,得装 strip-ansi。
现在有 util.stripVTControlCharacters 函数。
import { stripVTControlCharacters } from "node:util";
const text = "\u001B[4mUnderlined\u001B[0m";
console.log(stripVTControlCharacters(text));
原生处理,稳定可靠。
基本不需要再装第三方包了。
glob 匹配文件也原生了
匹配文件路径,以前必须用 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 了
删除整个目录树,以前都用 rimraf。
现在 fs.rm 直接支持递归删除。
import fs from "node:fs/promises";
await fs.rm("dist", { recursive: true, force: true });
Node.js 12.10 就有了,现在所有 LTS 版本都稳定支持。
递归创建目录也不用 mkdir 了
创建多级目录,以前要装 mkdir。
现在 fs.mkdir 原生支持。
await fs.mkdir("logs/app", { recursive: true });
Node.js 10.12 就加了,早就稳定了。
UUID 生成不用装包了
生成 UUID v4,以前要装 uuid 包。
现在 crypto 模块自带 randomUUID 函数。
import { randomUUID } from "node:crypto";
console.log(randomUUID());
Node.js 14.17 就有了,稳定版本。
Base64 编解码也原生支持了
以前要 polyfill atob 和 btoa 函数。
现在这俩已经是全局函数了。
const encoded = btoa("hello");
console.log(encoded);
console.log(atob(encoded));
Buffer 一直都有,现在加上 atob 和 btoa,浏览器和 Node.js 的代码终于统一了。
Node.js 20 左右加的,现在 LTS 版本都有。
URL 路由匹配有了 URLPattern
做路由匹配,以前要装 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 完全一样。
加载 .env 文件不一定要 dotenv 了
之前加载环境变量文件,必须装 dotenv。
现在可以用 --env-file 参数。
node --env-file=.env app.js
Node.js 20.10 加的实验性功能。
如果需要变量展开或多文件支持,dotenv 还是更强。
但简单场景下,原生的就够了。
EventTarget 也是全局的了
以前 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 了。
运行 TypeScript 不一定要 tsc 了
以前运行 .ts 文件,要装 TypeScript 编译器或 ts-node。
现在 Node.js 有实验性的 TypeScript 支持。
node --experimental-strip-types app.ts
Node.js 21 加的实验性功能。
不过这只是去掉类型标注,不做类型检查。
生产环境还是得用完整的 TypeScript 工具链。
为啥 Node.js 要把这些功能内置
看这些变化,能发现一个趋势。
以前需要外部依赖的功能,现在越来越多变成了核心功能。
这样做有几个好处。
减少依赖数量,项目更轻量。
降低供应链攻击风险,不用担心某个包被投毒。
代码在浏览器和服务端之间更容易移植。
能用就用起来
这些原生功能,浏览器支持好的就可以直接用了。
实验性的功能可以在开发环境先试试。
