miniframe-router:Express.JS应用程序的路由器

**miniframe-router** — 受 Ruby on Rails 启发的 Express.JS 应用程序的极简路由器。以下是我制作它的方法。

Image description

简单应用程序中路由的示例。

// Root routes
root("index#home");

// Basic CRUD routes
get("/users", "users#index");
get("/users/:id", "users#show");
post("/users", "users#create");
post("/users/:id", "users#update");
post("/users/:id/destroy", "users#destroy");

// Posts routes with scope
scope("blog", () => {
  get("/posts", "posts#index");
  get("/posts/:id", "posts#show");
  post("/posts", "posts#create");
  post("/posts/:id", "posts#update");
  post("/posts/:id/destroy", "posts#destroy");
});

语境

我已经有大约 10 年没有编写过 NodeJS 应用程序了。出于对 Telegram Mini Apps 的好奇,我决定构建几个简单的项目来探索这个新领域。

为此,我需要为应用程序的后端进行路由。现有的解决方案并没有给我留下深刻印象,所以我决定创建自己的路由器 — 简单、有效,并受到 Ruby on Rails 的启发。这也是刷新我创建 NPM 包知识的绝佳机会,这是我 9 年来从未做过的事情。

设计

对路由器的期望:

**路由在单独的文件中定义**

这简化了应用程序结构并避免使主应用程序文件混乱。

import {
  root,
  get,
  post,
  routeScope as scope,
  getRouter,
} from "miniframe-router";

// Root routes
root("index#home");

// Basic CRUD routes
get("/users", "users#index");
get("/users/:id", "users#show");
post("/users", "users#create");
post("/users/:id", "users#update");
post("/users/:id/destroy", "users#destroy");

// Posts routes with scope
scope("blog", () => {
  get("/posts", "posts#index");
  get("/posts/:id", "posts#show");
  post("/posts", "posts#create");
  post("/posts/:id", "posts#update");
  post("/posts/:id/destroy", "posts#destroy");
});

export default getRouter;

**路由器集成到主 ExpressJS 文件中**

应用程序的简单有效的入口点:`src/index.js`或`src/main.js`。

import express from "express";
import getRouter from "./routes"; // <<< DEFINE ROUTES

const app = express();
app.use(express.json());
app.use(getRouter()); // <<< APPLY ROUTES

app.listen(3000, () => {
  console.log("Demo app is running on http://localhost:3000");
});

**遵循连接控制器的惯例**

控制器位于“src/controllers”目录中。

MyApp
└── src
    ├── controllers
    │   ├── blog
    │   │   └── postsController.ts
    │   ├── indexController.ts
    │   └── usersController.ts
    ├── index.ts
    └── routes
        └── index.ts

文件结构

  • 路线在 src/routes/index.js 中定义。
  • 控制器包含处理请求的逻辑:
  • 例如:`src/controllers/usersController.ts` (或者 `.js`)。

    import { Request, Response } from "express";
    
    export const index = (req: Request, res: Response) => {
      res.send("List of all users");
    };
    
    export const show = (req: Request, res: Response) => {
      const { id } = req.params;
      res.send(`Showing details for user ${id}`);
    };
    
    export const create = (req: Request, res: Response) => {
      const userData = req.body;
      res.send(`Creating new user with data: ${JSON.stringify(userData)}`);
    };
    
    export const update = (req: Request, res: Response) => {
      const { id } = req.params;
      const userData = req.body;
      res.send(`Updating user ${id} with data: ${JSON.stringify(userData)}`);
    };
    
    export const destroy = (req: Request, res: Response) => {
      const { id } = req.params;
      res.send(`Deleting user ${id}`);
    };

    执行

    步骤:

  • 使用 Docker 创建开发容器。
  • 设置 ESBuild 以将 TypeScript 编译为 JavaScript。
  • 安装 Jest 进行测试。
  • 编写测试来验证路由器的第一个版本。
  • 实现路由器直到所有测试通过。
  • 恢复我长期未使用的 NPM 凭证(9 年后)。
  • 将 NPM 包发布为 1.0.0 版本。
  • 修复关键安装错误并删除版本 1.0.0 和 1.1.0。😄
  • 将路由器应用到一个有十几条路线的生产项目中。
  • 问答

    为什么要这么做?现有的解决方案已经很多了!

  • 它很有趣、很有用,并且有助于解决方案的多样性。
  • 为什么这么简单?难道不应该更复杂吗?

  • 遵循 KISS 原则。可以根据需要稍后添加复杂性。
  • 为什么要有控制器?它们不是没有必要吗?

  • 控制器对于小型项目来说很方便。像 Action/Operation 这样的更高抽象的解决方案更适合大型系统。
  • 这个解决方案有用吗?

  • 绝对如此!该路由器已在一个小型生产应用中使用,并且在数十条路由中表现完美。
  • 它能处理多大规模的项目?

  • miniframe-router 适用于具有数十条路由的应用程序。没有严格的大小限制。
  • 结论

    项目代码和文档:GitHub - miniframe-router

    NPM 包:miniframe-router

    点赞、分享和订阅!欢迎提出建设性反馈。

    作者页面:GitHub - the-teacher