为了充分发挥任何技术的威力,你需要按照最佳实践使用它。Node.js 最流行的特点是其异步事件驱动、非阻塞 I/O 处理。它从 JavaScript 的单线程事件循环模型中获得了大部分并发性和异步性。
因此,在本文中,我们将介绍使用 Node.js 进行编程性能的一些重要最佳实践。
网络上充满了涵盖 Web 开发基础的教程、文档、博客和视频。但通常,关于最佳实践的信息(和重要性)是我们在建立更多应用程序、在路上失败和成功时学到的。
→ 项目结构
- 将解决方案按组件分开: 我们应该将整个代码库划分为较小的组件,以便每个模块都有自己的文件夹,并确保每个模块保持简单和小巧。
- 分离业务逻辑和 API 路由
- 分层组件 将组件代码分为层:Web、服务和数据访问层。
- 将常用工具包装为 npm 包 将多次重复使用的相同代码组合成单个私有包文件,并在应用程序的各个位置使用该包。
→ 日志记录和错误处理实践
- 使用 Async-Await 或 Promise 进行异步错误处理。
- 集中处理错误。 处理错误的每个逻辑,如记录性能和发送有关错误的电子邮件,都应编写成这样的方式,以便所有 API、夜间作业和单元测试可以调试消息并在发生任何错误时调用此方法。
- 仅使用内置的 Error 对象。 内置的错误对象在我们的源代码和其他开源 JSON 包中处理错误方面采用统一的方法。
// throwing an Error from typical function, whether sync or async
if(!productToAdd)
throw new Error('How can I add new product when no value provided?');
// 'throwing' an Error from EventEmitter
const myEmitter = new MyEmitter();
myEmitter emit('error', new Error('whoops!'));
// 'throwing' an Error from a Promise
const addProduct = async (productToAdd) => {
try {
const existingProduct = await DAL.getProduct (productToAdd.id);
if (existingProduct !== null) {
throw new Error('Product already exists!');
}
} catch (err) {
// ...
}
}
- 使用良好的记录器以增加错误可见性。 👀 使用一组良好的日志记录工具,如 Pino 或 Log4js,将加快错误的发现和理解。所以忘记 console.log 吧。
- 捕获未处理的 Promise 拒绝。 🏈
- 测试你的应用程序 🧪 → 下面是 Node.js 应用程序最受欢迎的测试库(Mocha、Jest、Jasmine 和 AVA)
→ 代码风格实践
- 使用 Linting 包 有许多 Linting 工具可用,ESLint 是其中最受欢迎的 Linting 包之一,用于检查代码中可能存在的错误,否则你还可以 检查代码风格 以符合最佳实践标准**。**
- 在同一行上开始代码块的大括号。 (“为什么基于花括号放置的位置结果不同?”(StackOverflow)
- 为你的函数命名。
- 为变量、常量、函数和类使用命名约定。
- 在开头添加所需的模块,避免在函数内部添加。 这样做可以轻松识别整个文件的依赖项,并避免一些潜在的性能问题。
- 使用静态分析工具 诸如 SonarQube 和 Code Climate 的工具可以进行静态分析,帮助提高代码质量和性能,并使我们的代码可管理。我们可以将这些工具添加到 CI-CD 管道中,当它们检测到我们可以提高代码质量以提高性能的任何领域时,就会导致构建失败。
更多指南列在 https://developer.mozilla.org/en-US/docs/MDN/Guidelines/Code_guidelines/JavaScript 中。
→ 安全最佳实践
- 接受 Linter 安全规则。 我们可以使用 Linter 插件,如 eslint-plugin-security,在编写 Node.js 应用程序时捕获代码问题。 Linting 插件可以确保我们在开发过程中消除了易受攻击的代码。
- 检查易受攻击的依赖项。 我们可以使用工具,如 NPM audit 或 snyk.io,检查易受攻击的依赖项。
- 限制并发请求。
- **配置文件和环境变量:**light_bulb_on: 进行配置!作为安全最佳实践,我们应该使我们的应用程序级别的密钥易于从文件和环境变量中读取。我们还应将秘密保存在提交的代码之外,并创建一个配置文件层次结构,以便更轻松地访问。为此,需要一个完美无缺的配置设置。有一些可用的 Node.js 开发项目结构,可以帮助完成此操作,如 RC、nconf 和 config。
- 调整 HTTP 响应标头。 你的应用程序应该使用安全标头来防止攻击者使用常见攻击,如跨站点脚本(XSS)、点击劫持和其他恶意攻击。这些可以使用模块(如 helmet)轻松配置。
- 验证传入的 JSON 模式。 在执行实际逻辑之前,我们应该验证所有请求参数和正文参数以满足预期的模式。
- 防止查询注入漏洞。 为了防止 SQL/NoSQL 注入和其他恶意攻击,请始终使用 ORM/ODM 或支持命名或索引参数化查询并负责验证预期类型的用户输入的数据库库。
- 从客户端隐藏错误详细信息 🧐 确保不向客户端返回完整的错误对象,其中可能包含某些敏感应用程序详细信息,例如服务器文件路径、正在使用的第三方模块和应用程序的其他内部工作流程,攻击者可以从堆栈跟踪中找到的信息泄露。
→ 性能最佳实践
- 不要阻塞事件循环🚫 事件循环会注意到每个新的客户端连接,并协调生成响应。所有传入的请求和传出的响应都通过事件循环。这意味着,如果事件循环在任何时候花费的时间过长,所有当前和新的客户端都将无法获得机会。
示例:
// This callback will run quickly for small n and more slowly for large n.
// n^2 iterations before giving someone else a turn
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
console.log(`Iter ${i}.${j}`);
}
}
- 在生产之前清理依赖关系。
- 计划有效的缓存。
- 锁定依赖项。
评论(0)