关于Node.js,一定要学这个10+万Star项目 !!

  • Hey, 我是 沉浸式趣谈
  • 本文首发于【沉浸式趣谈】,我的个人博客 https://yaolifeng.com 也同步更新。
  • 转载请在文章开头注明出处和版权信息。
  • 如果本文对您有所帮助,请 点赞评论转发,支持一下,谢谢!

给大家分享一个关于 Node.js 的宝藏项目,目前已经有 10+万 Star,非常值得学习。

这个项目是啥?

Node.js Best Practices 是 GitHub 上一个超级热门的项目,

目前已经有 102k Star。它汇集了 100+条关于 Node.js 开发的最佳实践,涵盖了从项目架构到安全防范的方方面面。

  • 官网:https://practica.dev

  • Github:https://github.com/goldbergyoni/nodebestpractices

最厉害的是,它不像其他很多教程那样空洞地讲概念,每条最佳实践都包含了:

  1. 简明扼要的说明 - 适合快速浏览
  2. 详细的解释 - 为什么要这么做
  3. 代码例子 - 好代码 vs 坏代码的对比
  4. 相关资源链接 - 想深入了解的话可以继续学习

而且内容分门别类,按照项目结构、错误处理、编码规范、测试、安全、性能等主题组织,非常清晰。

实战案例

实践一:利用 CPU 多核能力

之前的问题:

1// app.js - 传统单进程启动方式 2const express = require('express'); 3const app = express(); 4// ...其他代码 5app.listen(3000, () => console.log('服务启动在3000端口'));

我们的服务器是 8 核 CPU,但上面的代码只能利用其中一个核心,大量计算资源被浪费。

参考最佳实践 5.6「利用 CPU 多核」,改进后:

1// app.js - 使用Node.js内置cluster模块 2const cluster = require('cluster'); 3const os = require('os'); 4const numCPUs = os.cpus().length; 5 6if (cluster.isMaster) { 7 console.log(`主进程 ${process.pid} 正在运行`); 8 9 // 根据CPU数量创建工作进程 10 for (let i = 0; i < numCPUs; i++) { 11 cluster.fork(); 12 } 13 14 cluster.on('exit', (worker, code, signal) => { 15 console.log(`工作进程 ${worker.process.pid} 已退出`); 16 // 当工作进程退出后,立即创建新的工作进程 17 cluster.fork(); 18 }); 19} else { 20 // 工作进程共享同一个TCP连接 21 const express = require('express'); 22 const app = express(); 23 24 // ...其他代码 25 26 app.listen(3000, () => { 27 console.log(`工作进程 ${process.pid} 监听端口3000`); 28 }); 29}

效果立竿见影!CPU 利用率从原来的 12%左右提升到了 80%以上,系统吞吐量提高了 6 倍多。

实践二:避免阻塞事件循环

之前的问题:

1app.get('/process-data', (req, res) => { 2 // 直接在API请求中执行CPU密集型操作 3 const result = processLargeDataSet(req.body.data); 4 res.json(result); 5}); 6 7function processLargeDataSet(data) { 8 // 一个CPU密集型的操作,处理几十万条记录 9 let result = []; 10 for (let i = 0; i < data.length; i++) { 11 // 复杂计算... 12 } 13 return result; 14}

这段代码在处理大量数据时会阻塞事件循环,导致其他用户请求无法得到响应,超时报错。

参考最佳实践 7.1「不要阻塞事件循环」,改进后:

1const { Worker } = require('worker_threads'); 2 3app.get('/process-data', (req, res) => { 4 const data = req.body.data; 5 6 // 创建一个工作线程来处理CPU密集型任务 7 const worker = new Worker('./data-processor.js', { 8 workerData: data, 9 }); 10 11 worker.on('message', result => { 12 res.json(result); 13 }); 14 15 worker.on('error', err => { 16 res.status(500).json({ error: err.message }); 17 }); 18}); 19 20// data-processor.js 21const { workerData, parentPort } = require('worker_threads'); 22 23function processLargeDataSet(data) { 24 // 复杂计算... 25 let result = []; 26 // 处理数据... 27 return result; 28} 29 30const result = processLargeDataSet(workerData); 31parentPort.postMessage(result);

改进后,即使在处理大数据集的时候,API 服务依然能流畅响应其他请求,用户体验大大提升。

实践三:使用中间件处理错误

之前的问题:

1app.get('/api/users/:id', (req, res) => { 2 try { 3 const user = getUserById(req.params.id); 4 if (!user) { 5 res.status(404).json({ error: 'User not found' }); 6 return; 7 } 8 res.json(user); 9 } catch (error) { 10 console.error('获取用户出错:', error); 11 res.status(500).json({ error: '服务器内部错误' }); 12 } 13}); 14 15// 每个路由都重复类似的错误处理代码...

这种方式导致每个路由都要写重复的错误处理代码,不仅冗余,也容易漏掉某些错误处理。

参考最佳实践 2.1「使用 Async-Await 或 Promise 处理异步错误」,改进后:

1// 统一的错误处理中间件 2app.use((err, req, res, next) => { 3 console.error('应用错误:', err); 4 5 // 根据错误类型返回不同状态码 6 if (err.name === 'NotFoundError') { 7 return res.status(404).json({ error: err.message }); 8 } 9 10 if (err.name === 'ValidationError') { 11 return res.status(400).json({ error: err.message }); 12 } 13 14 // 默认服务器错误 15 res.status(500).json({ error: '服务器内部错误' }); 16}); 17 18// 自定义错误类 19class NotFoundError extends Error { 20 constructor(message) { 21 super(message); 22 this.name = 'NotFoundError'; 23 } 24} 25 26// 路由变得简洁 27app.get('/api/users/:id', async (req, res, next) => { 28 try { 29 const user = await getUserById(req.params.id); 30 if (!user) { 31 throw new NotFoundError('用户不存在'); 32 } 33 res.json(user); 34 } catch (error) { 35 next(error); // 传递给错误处理中间件 36 } 37});

改进后,代码更加简洁,错误处理也更加统一和健壮。

我最推荐的几条最佳实践

在所有的实践中,以下五条是我认为对前端开发转 Node.js 的开发者最有价值的:

  1. 不要在客户端保存敏感信息 - 看似常识,但很多人会犯的错误
  2. 使用环境变量存储机密数据 - 不要把数据库密码直接写在代码里
  3. 优先使用内置方法 - 很多人喜欢引入 lodash,其实原生方法已经足够好
  4. 一次只处理一个错误 - 嵌套的错误处理是噩梦的开始

写在最后

说实话,之前我总觉得编码就是实现功能,能跑就行。

接触 Node.js Best Practices 后,我才明白写出高质量的 Node.js 代码需要考虑这么多方面。

最后,强烈推荐每一个使用 Node.js 的开发者都去看看这个项目。

它不仅告诉你 "怎么做",更重要的是解释了 "为什么要这么做",这对于提升开发能力至关重要。

点赞
收藏

评论区

加载中...

相关推荐

为什么 AI 总在 "靠谱" 和 "离谱" 之间反复横跳?

Hey,我是沉浸式趣谈本文首发于【沉浸式趣谈】,我的个人博客https://yaolifeng.com也同步更新。转载请在文章开头注明出处和版权信息。如果本文对您有所帮助,请点赞、评论、转发,支持一下,谢谢!AI真的懂你问的问题吗?AI—它可能是个「语言魔

从开发者到讲师,我第一次教跨行业AI写代码的心路历程

Hey,我是沉浸式趣谈本文首发于【沉浸式趣谈】,我的个人博客https://yaolifeng.com也同步更新。转载请在文章开头注明出处和版权信息。如果本文对您有所帮助,请点赞、评论、转发,支持一下,谢谢!最近经历了人生第一次当老师的经历,想和大家分享一

做定时任务,一定要用这个神库!!

Hey,我是沉浸式趣谈本文首发于【沉浸式趣谈】,我的个人博客https://yaolifeng.com也同步更新。转载请在文章开头注明出处和版权信息。如果本文对您有所帮助,请点赞、评论、转发,支持一下,谢谢!说实话,作为前端开发者,我们经常需要处理一些定时

做Docx预览,一定要做这个神库!!

Hey,我是沉浸式趣谈本文首发于【沉浸式趣谈】,我的个人博客https://yaolifeng.com也同步更新。转载请在文章开头注明出处和版权信息。如果本文对您有所帮助,请点赞、评论、转发,支持一下,谢谢!只需几行代码,你就能在浏览器中完美预览Word文

搞定 XLSX 预览?别瞎找了,这几个库(尤其最后一个)真香!

Hey,我是沉浸式趣谈本文首发于【沉浸式趣谈】,我的个人博客https://yaolifeng.com也同步更新。转载请在文章开头注明出处和版权信息。如果本文对您有所帮助,请点赞、评论、转发,支持一下,谢谢!该平台创作会佛系一点,更多文章在我的个人博客上更

关于我的第一个产品!

Hey,我是沉浸式趣谈本文首发于【沉浸式趣谈】,我的个人博客https://yaolifeng.com也同步更新。转载请在文章开头注明出处和版权信息。如果本文对您有所帮助,请点赞、评论、转发,支持一下,谢谢!嗨,大家好!👋你们有没有过这样的经历?一个绝妙