You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Node.js+Express+TypeScript路由选型及相关技术问题咨询

Node.js路由写法对比:Express原生 vs TypeORM声明式路由

Hey there! Great question—both routing patterns you mentioned are totally valid, but they’re designed for different scenarios and come with distinct tradeoffs. Let’s unpack this clearly:

1. 两种写法的正确性

First off, neither is "wrong"—they’re just different approaches tailored to different ecosystems:

  • The first one (router.get('/packages/:name', (req, res) => { ... })) is Express.js’s native imperative routing syntax. It’s the standard way to define routes directly in Express, tying the route path, HTTP method, and request handler together in one place.
  • The second one (export const Routes = [{ method: "post", route: "/user", controller: CustomerController, action: "createUser" }]) is a declarative routing pattern, commonly used in MVC (Model-View-Controller) architectures (like the one set up by typeorm init). It separates route definitions from the actual business logic (which lives in controllers).

2. 哪种写法更优?分场景看

The "better" choice depends on your project’s size, complexity, and architecture goals:

👉 优先选Express原生写法的场景

  • Small projects/prototypes: It’s fast to set up, requires no extra layers (like controllers), and keeps all route-related code in one spot. You can iterate quickly without over-engineering.
  • Simple APIs with minimal routes: If your API only has a handful of endpoints, this syntax is straightforward and avoids unnecessary abstraction.

👉 优先选TypeORM声明式写法的场景

  • Medium-to-large projects: This pattern enforces separation of concerns—route definitions are centralized, and business logic lives in dedicated controller classes. This makes code easier to maintain, test, and scale, especially for teams.
  • TypeScript-first projects: The declarative approach plays nicely with TypeScript’s type system. You get type safety for controllers and their methods, reducing runtime errors.
  • MVC-focused architectures: If you’re building an app that follows MVC principles, this routing style aligns perfectly with separating presentation (routes), business logic (controllers), and data access (models).

3. 如何给TypeORM式路由添加自定义中间件

Adding middleware to this declarative pattern is straightforward—you just extend the route objects with a middleware array, then handle it when registering routes with Express. Here’s how:

Step 1: Update your route configuration

// routes.ts
import { CustomerController } from './controllers/CustomerController';
import authMiddleware from './middleware/auth';
import validationMiddleware from './middleware/validation';

export const Routes = [
  { 
    method: "post", 
    route: "/user", 
    controller: CustomerController, 
    action: "createUser",
    middleware: [authMiddleware, validationMiddleware] // Add your custom middleware here
  },
  // Other routes...
];

Step 2: Register routes with middleware support

When setting up your Express app, iterate over the routes array and apply middleware before the controller action:

// app.ts
import express from 'express';
import { Routes } from './routes';

const app = express();

// Register all routes
Routes.forEach(route => {
  // Destructure route properties
  const { method, route: path, controller, action, middleware = [] } = route;
  
  // Apply middleware, then the controller action
  app[method](
    path,
    ...middleware, // Execute middleware in order
    (req, res) => {
      const controllerInstance = new controller();
      controllerInstance[action](req, res);
    }
  );
});

app.listen(3000, () => console.log('Server running on port 3000'));

This way, your middleware runs before the controller’s createUser method handles the request.

4. 两种写法的核心区别

Let’s summarize the key differences between the two patterns:

AspectExpress Native RoutingTypeORM Declarative Routing
Pattern TypeImperative (direct commands)Declarative (define "what" instead of "how")
Code OrganizationRoutes + handlers in one placeRoutes, controllers, and middleware are separated
Separation of ConcernsLow (handlers mix routing and business logic)High (routing is a mapping layer; logic lives in controllers)
Type Safety (TS)Manual type annotations neededBuilt-in type safety for controllers/actions
ScalabilityLess ideal for large apps (harder to manage many routes)Better for scaling (centralized route config, modular controllers)
Setup OverheadMinimal (no extra layers)Moderate (requires controller classes, route registration logic)

内容的提问来源于stack exchange,提问作者PawelC

火山引擎 最新活动