MK - Node.js工程师养成计划【完zheng】

229 阅读5分钟

Node.js工程师养成计划

核心代码,注释必读

// download:3w ukoou com

Node.js是一种开源的服务器端运行环境,利用它可以快速构建高性能、可扩展的网络应用程序。Node.js基于Chrome的V8引擎,允许JavaScript在服务器端运行,并且拥有很多优秀的特性,例如非阻塞I/O和事件驱动等。

下面我们来写一个简单的Node.js服务端项目,实现用户注册、登录和注销的功能。

  1. 初始化项目 对于Node.js项目,最先需要做的事情就是初始化项目,使用npm init命令生成一个package.json文件。
npm init
  1. 安装依赖 我们需要安装一些依赖,用来处理HTTP请求、密码加密、处理token等。
npm i express bcrypt jsonwebtoken mongoose cors
  1. 编写代码 我们创建一个index.js文件作为项目的入口文件,首先引入相关的模块和中间件,配置数据库、前端跨域方案,以及路由控制等。
const express = require("express");
const mongoose = require("mongoose"); //引入mongoose对象
const bcrypt = require("bcrypt"); //引入bcrypt对象,用于密码加密
const jwt = require("jsonwebtoken"); //引入jsonwebtoken对象,用于生成token
const cors = require("cors"); //引入cors对象,用于跨域
const app = express();
const port = 5000;
const dbURL = "mongodb://localhost:27017/node-auth";

app.use(express.json()); //解析json格式的请求体
app.use(cors()); //开启跨域

mongoose //连接数据库
   .connect(dbURL, { useNewUrlParser: true, useUnifiedTopology: true })
   .then(() => console.log("MongoDB connected..."))
   .catch((err) => console.log(err));

//定义用户模型
const Schema = mongoose.Schema;
const userSchema = new Schema({
   username: { type: String, required: true },
   password: { type: String, required: true },
});
const User = mongoose.model("User", userSchema);

//定义路由
app.post("/signup", (req, res) => {
   const { username, password } = req.body;
   bcrypt.hash(password, 10, (err, hash) => { //密码加密
       if (err) {
           res.status(500).json({ error: err });
       } else {
           User.create({ username: username, password: hash }) //向数据库中插入新用户信息
               .then(() => {
                   res.status(201).json({ message: "User created successfully" });
               })
               .catch((err) => {
                   res.status(500).json({ error: err });
               });
       }
   });
});

app.post("/login", (req, res) => {
   const { username, password } = req.body;
   User.findOne({ username: username }) //在数据库查找用户信息
       .then((user) => {
           if (user) {
               bcrypt.compare(password, user.password, (err, result) => { //密码验证
                   if (err) {
                       res.status(401).json({ message: "Authentication failed" });
                   }
                   if (result) {
                       const token = jwt.sign( //生成token
                           { username: user.username },
                           "secret_key",
                           { expiresIn: "1h" }
                       );
                       res.status(200).json({ message: "Authentication successful", token: token });
                   }
               });
           } else {
               res.status(401).json({ message: "Authentication failed" });
           }
       })
       .catch((err) => {
           res.status(500).json({ error: err });
       });
});

app.delete("/logout", (req, res) => {
   res.status(200).json({ message: "Logout successful" });
});

app.listen(port, () => {
   console.log(`Server started on port ${port}`);
});
  1. 测试 我们可以使用Postman等工具模拟POST、DELETE请求并检查返回结果,以检查实现是否正确。

Node.js工程师养成计划 Express框架

Express是目前Node.js生态系统内最流行的web框架之一,它提供了一种快速开发高质量web应用的方法。在实际项目中,我们会遇到代码结构混乱、维护难度大等问题,这时需要考虑对项目进行重构。以下是一个简单的Express框架重构项目教程。

  1. 准备工作 在进行重构前,我们需要对项目进行分析和排查,确定需要改进的部分。确认需要改进的部分后,创建一个branch用于进行重构,保证原有代码的稳定性。

  2. 结构优化 第一步是对项目的代码结构进行优化。通常情况下,我们在实际开发中会遇到这样一些问题:

  • 相关的代码分散在不同的文件中,不方便维护;
  • 路由和中间件的管理混乱,没有明确的组织结构;
  • 部分功能实现不够模块化,代码冗余。

我们可以通过以下方式优化代码结构:

  • 创建一个routes文件夹,用于存放所有路由相关的代码;
  • 创建一个middlewares文件夹,用于存放中间件;
  • 根据功能将相应的代码进行拆分,组织起来。

下面是一个目录结构示例:

├── config
│   ├── config.js
│   └── db.js
├── controllers
│   ├── auth.js
│   └── user.js
├── middlewares
│   ├── auth.js
│   ├── errorHandler.js
│   └── validator.js
├── models
│   ├── user.js
│   └── ...
├── routes
│   ├── auth.js
│   ├── user.js
│   └── ...
├── utils
│   └── ...
├── app.js
└── package.json
  1. 优化中间件 第二步是优化中间件,主要有以下几个方面:
  • 将所有中间件按照功能分组;
  • 将适用于所有路由的中间件提取出来;
  • 利用Node.js的异步特性,将中间件封装成promise形式,方便异步调用。

下面是一个中间件示例:

//middlewares/auth.js

const jwt = require("jsonwebtoken");
const { SECRET } = require("../config/config");

exports.verifyToken = (req, res, next) => {
  const token = req.headers["x-access-token"];
  if (!token) {
    return res.status(401).json({ message: "No token provided!" });
  }

  jwt.verify(token, SECRET, (err, decoded) => {
    if (err) {
      return res.status(401).json({ message: "Unauthorized!" });
    }
    req.userId = decoded.id;
    next();
  });
};

//通过promisify封装中间件
const { promisify } = require("util");
exports.verifyTokenAsync = promisify(exports.verifyToken);
  1. 优化路由 第三步是对路由进行优化。我们可以通过以下方式来优化路由:
  • 将路由分散到不同的文件中;
  • 使用路由前缀来提高可读性;
  • 把相似的路由组成子路由;
  • 引入路由级中间件进行处理。

下面是一个路由示例:

//routes/user.js

const router = require("express").Router();
const userController = require("../controllers/user");
const authMiddleware = require("../middlewares/auth");

router.get("/", userController.getAllUsers);
router.post("/", userController.createUser);

router.use("/:userId", authMiddleware.verifyToken);
router
  .route("/:userId")
  .get(userController.getUserById)
  .put(userController.updateUser)
  .delete(userController.deleteUser);

module.exports = router;
  1. 测试 在所有优化完成后,我们需要进行测试,保证所有功能都能正常工作。在此之前,需要额外关注功能是否存在破坏性的变化,确保新代码和模块对旧代码和模块的引用不会造成问题。

  2. 整合和发布 重构完成后,我们需要把所有代码整合到一个新版本的分支中,并发布项目。此时应该已经有一个较为清晰的项目结构,所有的路由、中间件、控制器都能明确地归属到特定的文件夹下,减少了对代码的无效搜索和浪费。自此,Express项目的重构就完成了。