你可能不知道的 15 个 Node.js 高级技巧(实战干货)
作为前端开发者,当我们掌握了 Node.js 的基础用法后,如何进一步提升开发效率?本文将分享 15 个你可能不知道的 Node.js 高级技巧,涵盖性能优化、调试技巧、实用 API 和工程化实践,助你成为 Node.js 高手!
一、路径处理:比 path.join
更高效的方式
// 传统方式
const path = require('path');
const fullPath = path.join(__dirname, 'files', 'test.txt');
// 更快的方式(Node.js 14+)
const fullPath2 = `${__dirname}/files/test.txt`;
为什么更快:现代 Node.js 对模板字符串的路径处理做了优化,简单场景下比 path.join
性能更好。
二、util.promisify
的隐藏用法
我们都知道可以用它转换回调函数,但它还能处理自定义的回调模式:
const util = require('util');
const fs = require('fs');
// 自定义回调函数(非标准 error-first 格式)
function customCallback(data, callback) {
callback(null, data.toUpperCase());
}
// 告诉 util.promisify 回调模式
customCallback[util.promisify.custom] = (data) => {
return new Promise((resolve) => {
customCallback(data, (err, result) => {
resolve(result);
});
});
};
const promisified = util.promisify(customCallback);
三、内存泄漏检测:--trace-gc
的进阶用法
node --trace-gc --trace-gc-verbose app.js
输出分析:
- 关注
Mark-sweep
和Scavenge
的频率 - 如果老生代(Old Space)持续增长,可能存在内存泄漏
进阶工具:
node --heap-prof app.js # 生成.heapprofile文件
用 Chrome DevTools 的 Memory 面板分析。
四、AsyncLocalStorage
实现全链路追踪
比 cls-hooked
更现代的解决方案:
const { AsyncLocalStorage } = require('async_hooks');
const asyncLocalStorage = new AsyncLocalStorage();
// 中间件示例
app.use((req, res, next) => {
asyncLocalStorage.run(new Map(), () => {
asyncLocalStorage.getStore().set('requestId', uuid());
next();
});
});
// 在任何地方获取上下文
function log() {
const store = asyncLocalStorage.getStore();
console.log(`[${store.get('requestId')}] Log message`);
}
五、Worker Threads 实战技巧
1. 共享内存的妙用:
const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {
const sharedBuffer = new SharedArrayBuffer(4);
const arr = new Int32Array(sharedBuffer);
new Worker(__filename, { workerData: sharedBuffer });
} else {
const arr = new Int32Array(workerData);
Atomics.add(arr, 0, 1); // 原子操作
}
2. 线程池实现:
const { Worker, isMainThread, threadId } = require('worker_threads');
class ThreadPool {
constructor(size) {
this.workers = Array(size).fill().map(() => new Worker(__filename));
}
dispatch(task) {
const worker = this.workers.find(w => !w.busy);
worker.busy = true;
worker.postMessage(task);
worker.once('message', () => worker.busy = false);
}
}
六、Buffer
的高阶用法
1. 内存复用池:
const bufferPool = [];
function getBuffer(size) {
const buf = bufferPool.find(b => b.length >= size) || Buffer.allocUnsafe(size);
return buf.slice(0, size);
}
function releaseBuffer(buf) {
bufferPool.push(buf);
}
2. 零拷贝转换:
const buf = Buffer.from('hello');
const arr = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
七、process
对象的隐藏功能
1. 实时内存监控:
setInterval(() => {
const mem = process.memoryUsage();
console.log(`RSS: ${(mem.rss / 1024 / 1024).toFixed(2)} MB`);
}, 1000);
2. 捕获未处理的 Promise 异常:
process.on('unhandledRejection', (err) => {
console.error('有Promise没catch!', err);
// 可以在这里上报错误
});
八、fs
模块的进阶技巧
1. 递归目录遍历(比 readdir
更快):
const { opendir } = require('fs/promises');
async function scan(dir) {
const dirHandle = await opendir(dir);
for await (const dirent of dirHandle) {
console.log(dirent.name);
}
}
2. 零拷贝文件发送:
const fs = require('fs');
const http = require('http');
http.createServer((req, res) => {
const stream = fs.createReadStream('bigfile.zip');
stream.pipe(res); // 零拷贝传输
}).listen(3000);
九、perf_hooks
性能分析
const { performance, PerformanceObserver } = require('perf_hooks');
const obs = new PerformanceObserver((items) => {
console.log(items.getEntries()[0].duration);
performance.clearMarks();
});
obs.observe({ entryTypes: ['measure'] });
performance.mark('start');
// 执行代码...
performance.mark('end');
performance.measure('耗时', 'start', 'end');
十、module
的冷门 API
1. 创建虚拟模块:
const { Module } = require('module');
const vm = require('vm');
const mod = new Module('virtual');
mod._compile('exports.hello = "world"', 'virtual.js');
console.log(mod.exports); // { hello: 'world' }
2. 劫持 require:
const realRequire = Module.prototype.require;
Module.prototype.require = function(id) {
if (id === 'axios') {
return realRequire.call(this, 'axios-mock');
}
return realRequire.call(this, id);
};
结语
掌握这些高级技巧后,你的 Node.js 开发水平将提升到一个新的层次。建议:
- 在项目中逐步尝试这些技巧
- 关注 Node.js 官方博客的更新
- 参与开源项目,学习更多实战经验
最后的小测验:你知道 Node.js 中如何实现真正的 Singleton 模式吗?(提示:利用 require
缓存机制)
欢迎在评论区分享你的 Node.js 技巧!如果觉得有用,请点赞收藏支持~