api
path 模块可以处理文件和目录路径。
import path from "node:path";
// 返回路径的最后一部分:file.txtconsole.log(path.basename("/home/user/file.txt"));
// 返回路径的目录名: /home/userconsole.log(path.dirname("/home/user/file.txt"));
// 返回路径的扩展名: .txtconsole.log(path.extname("/home/user/file.txt"));
// 连接路径: /home/user/file.txtconsole.log(path.join("/home/user", "file.txt"));
// 解析路径,返回当前目录的绝对路径console.log(path.resolve(__dirname, "./file.txt"));
// 解析路径,返回对象console.log(path.parse("/home/user/file.txt"));
// 格式化路径,返回字符串console.log( path.format({ dir: "/home/user", base: "file.txt", }));
// 返回路径分隔符:/console.log(path.sep());os 模块可以跟操作系统进行交互。
import os from "node:os";import { exec } from "node:child_process";
// 返回操作系统平台: win32,linux,darwinconsole.log(os.platform());
const platform = os.platform();
// 返回操作系统版本: 10.0.19041console.log(os.release());
// 返回操作系统类型: Windows_NT,Linux,Darwinconsole.log(os.type());
// 返回操作系统版本: Windows 11 Proconsole.log(os.version());
// 返回用户主目录: C:\Users\Administratorconsole.log(os.homedir());
// 返回系统CPU架构: x64console.log(os.arch());
// 返回操系统CPU信息: 12核console.log(os.cpus().length);
// 返回系统网络接口信息console.log(os.networkInterfaces());
// 打开浏览器访问指定urlconst open = (url) => { if (platform === "win32") { // exec 执行shell命令 exec(`start ${url}`); } else if (platform === "linux") { exec(`xdg-open ${url}`); } else if (platform === "darwin") { exec(`open ${url}`); }};
open("https://www.baidu.com");Process
Section titled “Process”process 模块是 Nodejs 操作当前进程和控制当前进程的 api 。
import process from "node:process";
// 返回系统CPU架构: x64console.log(process.arch());
// 返回操作系统平台: win32,linux,darwinconsole.log(process.platform);
// 返回当前工作目录console.log(process.cwd());
// 返回命令行参数,返回数组console.log(process.argv);
// 获取环境变量,返回对象console.log(process.env);
// 返回当前进程IDconsole.log(process.pid);
// 返回当前进程内存使用情况,返回对象console.log(process.memoryUsage());
// 退出进程process.exit(0);
// 杀死进程process.kill(process.pid, "SIGINT");Child process
Section titled “Child process”import { exec, execSync, spawn, spawnSync, execFile, execFileSync, fork,} from "node:child_process";import path from "node:path";
// 异步执行shell命令,适合进行较小规模的命令执行exec("node -v", (err, stdout, stderr) => { if (err) { console.error(err); } console.log(stdout.toString());});
// 同步执行shell命令,推荐使用这个const nodeVersion = execSync("node -v");console.log(nodeVersion.toString());
// 实时输出命令执行结果,适合进行较大规模的命令执行const { stdout } = spawn("netstat", ["-an"]);
stdout.on("data", (data) => { console.log(data.toString());});
stdout.on("close", () => { console.log("close");});
// 执行可执行文件execFile(path.resolve(__dirname, "child_process.js"), (err, stdout, stderr) => { if (err) { console.error(err); } console.log(stdout.toString());});
// 执行子进程,可以父子进程通信const child = fork(path.resolve(__dirname, "child_process.js"));
child.on("message", (message) => { console.log(message);});
child.send("hello");ffmpeg
Section titled “ffmpeg”// 基本格式转换execSync("ffmpeg -i input.mp4 output.avi", { stdio: "inherit" });
// 提取音频execSync("ffmpeg -i input.mp4 output.mp3", { stdio: "inherit" });
// 裁剪视频execSync("ffmpeg -i input.mp4 -ss 00:00:00 -t 00:00:10 output.mp4", { stdio: "inherit",});
// 加水印execSync( "ffmpeg -i input.mp4 -vf drawtext=text='demo':fontsize=20:x=(w-text_w)/2:y=(h-text_h)/2:fontcolor=white:box=1:boxcolor=black@0.5 output.mp4", { stdio: "inherit", });
// 删除水印execSync("ffmpeg -i input.mp4 -vf delogo=x=10:y=10:w=100:h=100 output.mp4", { stdio: "inherit",});pngquant
Section titled “pngquant”// 压缩png图片exec("pngquant origin.png --quality=80 --output image.png");Events
Section titled “Events”Nodejs 事件模型采用了发布订阅设计模式 。
import { EventEmitter } from "node:events";
const myEmitter = new EventEmitter();myEmitter.setMaxListeners(20);
// 订阅事件,默认只能10个myEmitter.on("event-1", (name) => { console.log(`${name} event-1 occurred!`);});// 发布事件myEmitter.emit("event-1", "张三");import { exec } from "node:child_process";import util from "node:util";
// 返回一个新的函数const execPromise = util.promisify(exec);
execPromise("node -v") .then((res) => { console.log(res); }) .catch((err) => { console.error(err); });
// 实现promisifyconst promisify = (fn) => { return (...args) => { return new Promise((resolve, reject) => { fn(...args, (err, ...values) => { if (err) { reject(err); } if (values && values.length > 1) { let obj = {}; for (const key in values) { obj[key] = values[key]; } resolve(obj); } else { resolve(values[0]); } }); }); };};
const fn = (type) => { if (type == 1) { return Promise.resolve("success"); } else { return Promise.reject("error"); }};
// 把Promise函数变成回调函数const cb = util.callbackify(fn);
cb(1, (err, val) => { console.log(err, val);});File system
Section titled “File system”fs 模块可以执行读取文件、写入文件、创建目录等操作。
import * as fs from "node:fs";import * as fs2 from "node:fs/promises";
// 读取文件// fs.readFile(// "./fs.js",// {// encoding: "utf-8",// flag: "r",// },// (err, data) => {// if (err) {// console.error(err);// }// console.log(data);// }// );
// const data = fs.readFileSync("./fs.js");// console.log(data.toString("utf-8"));
fs2 .readFile("./fs.js") .then((data) => { console.log(data); }) .catch((err) => { console.error(err); });
// 可读流,场景:大文件读取const rs = fs.createReadStream("./fs.js");rs.on("data", (chunk) => { console.log(chunk.toString());});rs.on("end", () => { console.log("end");});
// 创建文件夹,支持递归创建fs.mkdirSync("./test", { recursive: true });
// 删除文件夹fs.rmSync("./test", { recursive: true });
// 重命名文件fs.renameSync("./fs.js", "./fs2.js");
// 监听文件变化fs.watch("./fs.js", (eventType, filename) => { console.log(eventType, filename);});
// 写入文件fs.writeFileSync("./fs.js", "console.log('hello')", { flag: "a" });
// 追加写入文件fs.appendFileSync("./fs.js", "console.log('vue')");
// 创建可写流let ws = fs.createWriteStream("./fs.js");
let arr = ["1", "2", "3"];
arr.forEach((item) => { ws.write(item + "\n");});
ws.end();
ws.on("finish", () => { console.log("write finished");});
// 硬链接fs.linkSync("./fs.js", "./fs2.js");
// 软链接,需要管理员权限运行fs.symlinkSync("./fs.js", "./fs3.js");Crypto
Section titled “Crypto”import crypto from "node:crypto";
// 对称加密let key = crypto.randomBytes(32);let iv = Buffer.from(crypto.randomBytes(16));
const hash = crypto .createCipheriv("aes-256-cbc", key, iv) .update("HELLO WORLD", "utf8", "hex") .final("hex");
console.log(hash);
// 解密crypto .createDecipheriv("aes-256-cbc", key, iv) .update(hash, "hex", "utf8") .final("utf8");
console.log(decrypted);
// 非对称加密const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { modulusLength: 4096,});
const encrypted = crypto.publicEncrypt(publicKey, Buffer.from("Hello World"));
console.log(encrypted.toString("hex"));
const decrypted = crypto.privateDecrypt(privateKey, encrypted);
console.log(decrypted.toString("utf8"));
// 哈希加密const hash1 = crypto.createHash("sha256").update("Hello World").digest("hex");
console.log(hash1);gzip 常用于文件压缩、网络传输和 HTTP 响应的内容编码。
import zlib from "node:zlib";import fs from "node:fs";import http from "node:http";
// 压缩文件// const readStream = fs.createReadStream("./vue.md");// const writeStream = fs.createWriteStream("./vue.md.gz");
// const gzip = zlib.createGzip();
// readStream.pipe(gzip).pipe(writeStream);
// 解压文件const readStream = fs.createReadStream("./vue.md.gz");const writeStream = fs.createWriteStream("./vue.md");
const gunzip = zlib.createGunzip();
readStream.pipe(gunzip).pipe(writeStream);
// gzip 压缩应用const server = http.createServer((req, res) => { const text = "Hello World".repeat(10000); res.setHeader("Content-Type", "text/plain;charset=utf-8"); res.setHeader("Content-Encoding", "gzip"); let result = zlib.gzipSync(text); res.end(result);});
server.listen(3000, () => { console.log("server is running on port 3000");});deflate
Section titled “deflate”Web 服务器
Section titled “Web 服务器”import http from "node:http";import url from "node:url";
// web 服务器const server = http.createServer((req, res) => { const { pathname, query } = url.parse(req.url, true); console.log(pathname, query);
if (req.method === "POST") { if (pathname === "/login") { let data = ""; req.on("data", (chunk) => { data += chunk; }); req.on("end", () => { res.statusCode = 200; res.setHeader("Content-Type", "application/json"); res.end(JSON.stringify(data)); }); } else { res.statusCode = 404; res.end("NOT FOUND"); } } else if (req.method === "GET") { if (pathname === "/get") { console.log(query); res.statusCode = 200; res.end("GET"); } else { res.statusCode = 404; res.end("NOT FOUND"); } } else { res.end("NOT FOUND"); }});
server.listen(3000, () => { console.log("server is running on port 3000");});TCP 通讯
Section titled “TCP 通讯”server.js;import net from "node:net";
const server = net.createServer((socket) => { setInterval(() => { socket.write("Hello"); }, 1000);
socket.on("data", (data) => { console.log(data.toString()); });});
server.listen(3000, () => { console.log("server is running on port 3000");});import net from "node:net";
const client = net.createConnection({ host: "localhost", port: 3000,});
client.on("data", (data) => { console.log(data.toString());});
client.write("Hi");import net from "node:net";
const server = net.createServer((socket) => { socket.write("HTTP/1.1 200 OK\r\n"); socket.write("Content-Type: text/html\r\n"); socket.write("\r\n"); socket.write("<h1>Hello World</h1>");
socket.on("data", (data) => { console.log(data.toString()); });});
server.listen(3000, () => { console.log("server is running on port 3000");});HTTP缓存
Section titled “HTTP缓存”HTTP缓存分为强缓存和协商缓存。这两种缓存都通过HTTP响应头来控制,目的是提高网站性能。
强缓存之后则不需要向服务器发送请求,而是从浏览器缓存中读取。
import express from 'express'import cors from 'cors'
// Expires的判断机制是:当客户端请求资源时,会获取本地时间戳,然后拿本地时间戳与 Expires 设置的时间做对比,如果对比成功,走强缓存,对比失败,则对服务器发起请求。
const app = express()app.use(cors())
// 静态资源缓存app.use(express.static('./static', { maxAge: 1000 * 60 * 60, lastModified: true,}))
// 动态资源缓存// Expires 强缓存app.get('/api', (req, res) => { res.setHeader('Expires', new Date('2025-10-10 23:17:00').toUTCString()) //设置过期时间 res.send("ok")})
// Cache-Control 强缓存app.get('/cache', (req, res) => { res.setHeader('Cache-Control', 'public, max-age=60') //缓存60秒 res.send("ok")})
app.listen(3000, () => { console.log('Server started on port 3000')})<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><button id="btn">Send</button>
<script> const btn = document.getElementById('btn') btn.addEventListener('click', () => { fetch('http://localhost:8080/api') })</script>
</body></html>import express from 'express'import cors from 'cors'import fs from 'node:fs'import crypto from 'node:crypto'
// 获取文件最后修改时间const getFileModifyTime = () => { return fs.statSync('./index.js').mtime.toISOString()}
// 根据文件生成hash值const getFileHash = () => { return crypto.createHash('sha256').update(fs.readFileSync('index.js')).digest('hex')}
const app = express()app.use(cors())
// Last-Modified:根据文件最后修改时间// app.get('/api', (req, res) => {// res.setHeader('Cache-Control', 'no-cache, max-age=2592000') //no-cache表示走协商缓存// const ifModifiedSince = req.headers['if-modified-since'] //获取浏览器上次修改时间// res.setHeader('Last-Modified', getFileModifyTime())// if (ifModifiedSince && ifModifiedSince === getFileModifyTime()) {// console.log('304')// res.statusCode = 304// res.end('are you ok')// return// } else {// console.log('200')// res.end('ok')// }// })
app.get('/use', (req, res) => { res.setHeader('Cache-Control', 'no-cache, max-age=2592000') const etag = getFileHash() const ifNoneMatch = req.headers['if-none-match'] if (ifNoneMatch === etag) { res.sendStatus(304) return } res.setHeader('ETag', etag) res.send('ok')})
app.listen(3000, () => { console.log('App listening on port 3000')})