Node.js 内置模块
不用装依赖就能用的那些模块,按用途分类速查。
Key Points`node:` 前缀明确表示内置模块,避免和同名第三方包冲突。
分类速查
| Category | Modules |
|---|---|
| 路径与文件 | path fs os url |
| 网络 | http https net dgram dns |
| 流与缓冲 | stream buffer zlib string_decoder |
| 加密 | crypto tls |
| 进程与线程 | process child_process worker_threads cluster |
| 工具 | util events assert timers readline |
| 测试 | node:test node:assert |
path 与 url
JavaScript
const path = require('node:path');
const { fileURLToPath, pathToFileURL } = require('node:url');
console.log(path.sep); // 平台分隔符
console.log(path.posix.join('a', 'b')); // 强制 POSIX 风格
const u = new URL('https://example.com/api/users?page=2&size=10');
console.log(u.pathname, u.searchParams.get('page'));Output
\
a/b
/api/users 2os
JavaScript
const os = require('node:os');
console.log(os.platform(), os.arch());
console.log('CPU', os.cpus().length, '核');
console.log('内存', (os.totalmem() / 1024 ** 3).toFixed(1), 'GB');
console.log('可用', (os.freemem() / 1024 ** 3).toFixed(1), 'GB');
console.log('临时目录', os.tmpdir());
console.log('主机名', os.hostname());Output
win32 x64
CPU 8 核
内存 15.9 GB
可用 6.2 GB
临时目录 C:\Users\Administrator\AppData\Local\Temp
主机名 DESKTOP-8K2J4M1crypto
JavaScript
const crypto = require('node:crypto');
// 哈希
console.log(crypto.createHash('sha256').update('hello').digest('hex'));
// 随机 UUID
console.log(crypto.randomUUID());
// 安全随机 token
console.log(crypto.randomBytes(16).toString('hex'));
// 加盐密码哈希(登录场景的正确做法)
const salt = crypto.randomBytes(16);
const hash = crypto.scryptSync('password', salt, 64).toString('hex');
console.log(hash.length);Output
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
3f2504e0-4f89-41d3-9a0c-0305e82c3301
8f3c2b1a9d4e5f60718293a4b5c6d7e8
128Store passwords with
scrypt or bcrypt, never a bare md5/sha256. Bare hashes fall to rainbow tables, and salt alone only halves the problem — scrypt's computational cost is what matters.zlib
JavaScript
const zlib = require('node:zlib');
const { promisify } = require('node:util');
const gzip = promisify(zlib.gzip);
const gunzip = promisify(zlib.gunzip);
const packed = await gzip(Buffer.from('重复的数据'.repeat(1000)));
console.log('压缩后', packed.length, '字节');
const back = await gunzip(packed);
console.log('解压后', back.length, '字节');Output
压缩后 118 字节
解压后 15000 字节node:test
JavaScript
const test = require('node:test');
const assert = require('node:assert');
test('加法', () => {
assert.strictEqual(1 + 1, 2);
});
test('异步', async () => {
const v = await Promise.resolve(42);
assert.ok(v > 0);
});Output
$ node --test
▶ 加法
✔ 加法 (0.8ms)
▶ 异步
✔ 异步 (0.4ms)
ℹ pass 2
ℹ fail 0Node 18+ ships a test runner, so small projects need no Jest. node --test discovers *.test.js and files under test/.
分类速查
| 类别 | 模块 |
|---|---|
| 路径与文件 | path fs os url |
| 网络 | http https net dgram dns |
| 流与缓冲 | stream buffer zlib string_decoder |
| 加密 | crypto tls |
| 进程与线程 | process child_process worker_threads cluster |
| 工具 | util events assert timers readline |
| 测试 | node:test node:assert |
path 与 url
JavaScript
const path = require('node:path');
const { fileURLToPath, pathToFileURL } = require('node:url');
console.log(path.sep); // 平台分隔符
console.log(path.posix.join('a', 'b')); // 强制 POSIX 风格
const u = new URL('https://example.com/api/users?page=2&size=10');
console.log(u.pathname, u.searchParams.get('page'));Output
\
a/b
/api/users 2os
JavaScript
const os = require('node:os');
console.log(os.platform(), os.arch());
console.log('CPU', os.cpus().length, '核');
console.log('内存', (os.totalmem() / 1024 ** 3).toFixed(1), 'GB');
console.log('可用', (os.freemem() / 1024 ** 3).toFixed(1), 'GB');
console.log('临时目录', os.tmpdir());
console.log('主机名', os.hostname());Output
win32 x64
CPU 8 核
内存 15.9 GB
可用 6.2 GB
临时目录 C:\Users\Administrator\AppData\Local\Temp
主机名 DESKTOP-8K2J4M1crypto
JavaScript
const crypto = require('node:crypto');
// 哈希
console.log(crypto.createHash('sha256').update('hello').digest('hex'));
// 随机 UUID
console.log(crypto.randomUUID());
// 安全随机 token
console.log(crypto.randomBytes(16).toString('hex'));
// 加盐密码哈希(登录场景的正确做法)
const salt = crypto.randomBytes(16);
const hash = crypto.scryptSync('password', salt, 64).toString('hex');
console.log(hash.length);Output
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
3f2504e0-4f89-41d3-9a0c-0305e82c3301
8f3c2b1a9d4e5f60718293a4b5c6d7e8
128存密码用
scrypt 或 bcrypt,**不要用 md5 / sha256 裸哈希**。裸哈希可以被彩虹表秒破,加盐也只能挡住一半;scrypt 的计算成本才是关键。zlib
JavaScript
const zlib = require('node:zlib');
const { promisify } = require('node:util');
const gzip = promisify(zlib.gzip);
const gunzip = promisify(zlib.gunzip);
const packed = await gzip(Buffer.from('重复的数据'.repeat(1000)));
console.log('压缩后', packed.length, '字节');
const back = await gunzip(packed);
console.log('解压后', back.length, '字节');Output
压缩后 118 字节
解压后 15000 字节node:test
JavaScript
const test = require('node:test');
const assert = require('node:assert');
test('加法', () => {
assert.strictEqual(1 + 1, 2);
});
test('异步', async () => {
const v = await Promise.resolve(42);
assert.ok(v > 0);
});Output
$ node --test
▶ 加法
✔ 加法 (0.8ms)
▶ 异步
✔ 异步 (0.4ms)
ℹ pass 2
ℹ fail 0Node 18+ 内置测试运行器,写小项目不用装 Jest。node --test 会自动找 *.test.js 和 test/ 目录下的文件。