【Node.js】Web开发框架

个人主页:Guiat
归属专栏:node.js

文章目录

  • [1. Node.js Web框架概述](#1. Node.js Web框架概述)
    • [1.1 Web框架的作用](#1.1 Web框架的作用)
    • [1.2 Node.js主要Web框架生态](#1.2 Node.js主要Web框架生态)
    • [1.3 框架选择考虑因素](#1.3 框架选择考虑因素)
  • [2. Express.js](#2. Express.js)
    • [2.1 Express.js概述](#2.1 Express.js概述)
    • [2.2 基本用法](#2.2 基本用法)
      • [2.2.1 安装Express](#2.2.1 安装Express)
      • [2.2.2 创建基本服务器](#2.2.2 创建基本服务器)
    • [2.3 路由](#2.3 路由)
    • [2.4 中间件](#2.4 中间件)
    • [2.5 请求和响应](#2.5 请求和响应)
    • [2.6 完整的Express应用结构](#2.6 完整的Express应用结构)
  • [3. Koa.js](#3. Koa.js)
    • [3.1 Koa.js概述](#3.1 Koa.js概述)
    • [3.2 基本用法](#3.2 基本用法)
      • [3.2.1 安装Koa](#3.2.1 安装Koa)
      • [3.2.2 创建基本服务器](#3.2.2 创建基本服务器)
    • [3.3 中间件和上下文](#3.3 中间件和上下文)
    • [3.4 Koa与Express对比](#3.4 Koa与Express对比)
  • [4. Nest.js](#4. Nest.js)
    • [4.1 Nest.js概述](#4.1 Nest.js概述)
    • [4.2 基本用法](#4.2 基本用法)
      • [4.2.1 安装Nest.js](#4.2.1 安装Nest.js)
      • [4.2.2 主要组件](#4.2.2 主要组件)
    • [4.3 依赖注入](#4.3 依赖注入)
    • [4.4 中间件、守卫和拦截器](#4.4 中间件、守卫和拦截器)
  • [5. Fastify](#5. Fastify)
    • [5.1 Fastify概述](#5.1 Fastify概述)
    • [5.2 基本用法](#5.2 基本用法)
      • [5.2.1 安装Fastify](#5.2.1 安装Fastify)
      • [5.2.2 创建服务器](#5.2.2 创建服务器)
    • [5.3 Schema验证和序列化](#5.3 Schema验证和序列化)
    • [5.4 插件系统](#5.4 插件系统)
    • [5.5 与Express和Koa性能对比](#5.5 与Express和Koa性能对比)
  • [6. Next.js](#6. Next.js)
    • [6.1 Next.js概述](#6.1 Next.js概述)
    • [6.2 基本用法](#6.2 基本用法)
      • [6.2.1 创建Next.js应用](#6.2.1 创建Next.js应用)
      • [6.2.2 页面和路由](#6.2.2 页面和路由)
    • [6.3 数据获取方法](#6.3 数据获取方法)
    • [6.4 API路由](#6.4 API路由)
    • [6.5 中间件和布局](#6.5 中间件和布局)
  • [7. Hapi.js](#7. Hapi.js)
    • [7.1 Hapi.js概述](#7.1 Hapi.js概述)
    • [7.2 基本用法](#7.2 基本用法)
      • [7.2.1 安装Hapi](#7.2.1 安装Hapi)
      • [7.2.2 创建服务器](#7.2.2 创建服务器)
    • [7.3 路由和处理程序](#7.3 路由和处理程序)
    • [7.4 插件和扩展](#7.4 插件和扩展)
    • [7.5 验证和认证](#7.5 验证和认证)
  • [8. 全栈框架: AdonisJS和Sails.js](#8. 全栈框架: AdonisJS和Sails.js)
    • [8.1 AdonisJS概述](#8.1 AdonisJS概述)
    • [8.2 AdonisJS基本用法](#8.2 AdonisJS基本用法)
      • [8.2.1 创建AdonisJS应用](#8.2.1 创建AdonisJS应用)
      • [8.2.2 AdonisJS应用结构](#8.2.2 AdonisJS应用结构)
      • [8.2.3 路由和控制器](#8.2.3 路由和控制器)
    • [8.3 Sails.js概述](#8.3 Sails.js概述)
    • [8.4 Sails.js基本用法](#8.4 Sails.js基本用法)
      • [8.4.1 创建Sails.js应用](#8.4.1 创建Sails.js应用)
      • [8.4.2 模型和API](#8.4.2 模型和API)
      • [8.4.3 路由配置](#8.4.3 路由配置)
  • [9. 专业领域框架](#9. 专业领域框架)
    • [9.1 Loopback - API框架](#9.1 Loopback - API框架)
      • [9.1.1 基本使用](#9.1.1 基本使用)
    • [9.2 Strapi - 内容管理框架](#9.2 Strapi - 内容管理框架)
      • [9.2.1 基本使用](#9.2.1 基本使用)
  • [10. 框架选择指南与比较](#10. 框架选择指南与比较)
    • [10.1 框架特性对比](#10.1 框架特性对比)
    • [10.2 适用场景选择](#10.2 适用场景选择)

正文

1. Node.js Web框架概述

Node.js的生态系统提供了多种Web开发框架,它们各自具有不同的特点和适用场景。这些框架帮助开发者快速构建高性能、可维护的Web应用程序。

1.1 Web框架的作用

  • 简化HTTP服务器的创建
  • 提供路由管理
  • 集成中间件系统
  • 统一错误处理
  • 提供模板引擎支持
  • 简化API开发
  • 改善应用程序结构

1.2 Node.js主要Web框架生态

Node.js Web框架 Express.js Koa.js Hapi.js Nest.js Fastify Next.js Adonis.js Sails.js Loopback Middleware-based Async/Await友好 配置驱动 TypeScript优先 性能导向 React SSR/SSG 全栈MVC 企业级API API开发

1.3 框架选择考虑因素

mindmap root((Web框架选择)) 性能需求 高并发应用 低延迟 资源消耗 开发效率 开发速度 学习曲线 社区支持 项目复杂度 小型项目 中型应用 企业级应用 团队技能 TypeScript经验 现有框架经验 架构偏好 生态系统 中间件 ORM支持 插件丰富度 应用类型 REST API GraphQL 实时应用 静态网站

2. Express.js

2.1 Express.js概述

Express.js是Node.js最流行的Web框架,提供了简单而灵活的API,适用于各种Web应用和API开发。
客户端请求 Express应用 路由 中间件1 中间件2 路由处理器 响应 客户端

2.2 基本用法

2.2.1 安装Express

bash 复制代码
npm install express

2.2.2 创建基本服务器

javascript 复制代码
const express = require('express');
const app = express();
const port = 3000;

// 路由处理
app.get('/', (req, res) => {
  res.send('Hello World!');
});

// 启动服务器
app.listen(port, () => {
  console.log(`服务器运行在 http://localhost:${port}`);
});

2.3 路由

javascript 复制代码
// 基本路由
app.get('/users', (req, res) => {
  res.json([{ name: 'John' }, { name: 'Jane' }]);
});

app.post('/users', (req, res) => {
  // 创建用户
  res.status(201).json({ success: true });
});

// 参数路由
app.get('/users/:id', (req, res) => {
  const userId = req.params.id;
  res.json({ id: userId, name: 'John Doe' });
});

// 路由模块化
const usersRoutes = express.Router();

usersRoutes.get('/', (req, res) => { /* ... */ });
usersRoutes.post('/', (req, res) => { /* ... */ });
usersRoutes.get('/:id', (req, res) => { /* ... */ });

app.use('/api/users', usersRoutes);

2.4 中间件

请求 全局中间件 路由特定中间件 路由处理器 响应

javascript 复制代码
// 内置中间件
app.use(express.json()); // 解析JSON请求体
app.use(express.urlencoded({ extended: true })); // 解析URL编码的请求体
app.use(express.static('public')); // 提供静态文件

// 自定义中间件
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url} at ${new Date()}`);
  next(); // 继续下一个中间件
});

// 路由特定中间件
const authenticate = (req, res, next) => {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ error: '未授权' });
  }
  // 验证token...
  next();
};

app.get('/protected', authenticate, (req, res) => {
  res.json({ message: '受保护的数据' });
});

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: '服务器内部错误' });
});

2.5 请求和响应

javascript 复制代码
// 请求对象(req)
app.get('/example', (req, res) => {
  console.log(req.query);     // 查询参数
  console.log(req.params);    // 路由参数
  console.log(req.body);      // 请求体
  console.log(req.headers);   // 请求头
  console.log(req.cookies);   // Cookies (需要cookie-parser)
  console.log(req.ip);        // 客户端IP
  console.log(req.path);      // 请求路径
  console.log(req.method);    // HTTP方法
  
  // 响应对象(res)
  res.status(200);            // 设置状态码
  res.set('Content-Type', 'application/json'); // 设置响应头
  res.cookie('name', 'value', { maxAge: 900000 }); // 设置cookie
  res.json({ data: 'JSON响应' }); // 发送JSON响应
  res.send('文本响应');       // 发送通用响应
  res.sendFile('/path/to/file.pdf'); // 发送文件
  res.download('/report.pdf'); // 下载文件
  res.redirect('/new-page'); // 重定向
  res.render('template', { title: '模板渲染' }); // 渲染模板
});

2.6 完整的Express应用结构

复制代码
project-root/
├── config/                  # 配置文件
│   ├── database.js
│   └── app.js
├── controllers/             # 控制器
│   ├── userController.js
│   └── productController.js
├── middleware/              # 中间件
│   ├── auth.js
│   └── errorHandler.js
├── models/                  # 数据模型
│   ├── User.js
│   └── Product.js
├── routes/                  # 路由
│   ├── userRoutes.js
│   └── productRoutes.js
├── public/                  # 静态资源
│   ├── css/
│   ├── js/
│   └── images/
├── views/                   # 视图模板
│   ├── layouts/
│   ├── users/
│   └── products/
├── tests/                   # 测试
│   ├── unit/
│   └── integration/
├── app.js                   # 主应用文件
├── server.js                # 服务器启动文件
├── package.json
└── .env                     # 环境变量

3. Koa.js

3.1 Koa.js概述

Koa是由Express团队开发的更轻量级、更富有表现力的Node.js Web框架,专为异步编程设计,利用async/await特性提供更简洁的中间件机制。
客户端请求 Koa应用 中间件1 中间件2 中间件3 响应处理 中间件3 返回 中间件2 返回 中间件1 返回 响应

3.2 基本用法

3.2.1 安装Koa

bash 复制代码
npm install koa

3.2.2 创建基本服务器

javascript 复制代码
const Koa = require('koa');
const app = new Koa();
const port = 3000;

// 中间件
app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(port, () => {
  console.log(`服务器运行在 http://localhost:${port}`);
});

3.3 中间件和上下文

javascript 复制代码
// 错误处理中间件
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.status = err.statusCode || 500;
    ctx.body = {
      message: err.message
    };
    ctx.app.emit('error', err, ctx);
  }
});

// 数据解析中间件
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());

// 路由中间件
const Router = require('@koa/router');
const router = new Router();

router.get('/', async (ctx) => {
  ctx.body = { message: '首页' };
});

router.get('/users/:id', async (ctx) => {
  const userId = ctx.params.id;
  ctx.body = { id: userId, name: 'John Doe' };
});

app.use(router.routes());
app.use(router.allowedMethods());

// 上下文操作示例
app.use(async ctx => {
  // 请求数据
  console.log(ctx.request.query);  // 查询参数
  console.log(ctx.request.body);   // 请求体 (需要bodyParser)
  console.log(ctx.params);         // 路由参数 (需要路由中间件)
  
  // 响应设置
  ctx.status = 200;                // 状态码
  ctx.set('X-Custom-Header', 'value'); // 自定义响应头
  ctx.type = 'application/json';   // 内容类型
  ctx.body = { data: 'success' };  // 响应体
  
  // Cookies
  ctx.cookies.set('name', 'value', { maxAge: 86400000 });
  const cookie = ctx.cookies.get('name');
});

3.4 Koa与Express对比

Web框架对比 Express Koa 优点 成熟稳定 社区庞大 中间件丰富 简单直观 缺点 回调地狱 错误处理复杂 优点 async/await支持 更好的错误处理 更简洁的API 可组合中间件 缺点 学习曲线 需要额外模块

4. Nest.js

4.1 Nest.js概述

Nest.js是一个用于构建高效、可靠、可扩展的服务器端应用程序的渐进式Node.js框架,它结合了面向对象编程、函数式编程和函数响应式编程的元素。
Nest.js架构 模块Module 控制器Controller 提供者Provider 中间件Middleware 管道Pipe 守卫Guard 拦截器Interceptor 异常过滤器ExceptionFilter 功能封装 处理请求 提供服务 处理HTTP请求 数据转换/验证 权限验证 响应拦截/修改 异常处理

4.2 基本用法

4.2.1 安装Nest.js

bash 复制代码
npm i -g @nestjs/cli
nest new project-name

4.2.2 主要组件

typescript 复制代码
// 控制器 (users.controller.ts)
import { Controller, Get, Post, Body, Param, UseGuards } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { AuthGuard } from '../auth/auth.guard';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }

  @Post()
  @UseGuards(AuthGuard)
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }
}

// 服务 (users.service.ts)
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { User } from './entities/user.entity';

@Injectable()
export class UsersService {
  private readonly users: User[] = [];

  create(createUserDto: CreateUserDto): User {
    const user = { id: this.users.length + 1, ...createUserDto };
    this.users.push(user);
    return user;
  }

  findAll(): User[] {
    return this.users;
  }

  findOne(id: number): User {
    return this.users.find(user => user.id === id);
  }
}

// 模块 (users.module.ts)
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';

@Module({
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService]
})
export class UsersModule {}

// 主模块 (app.module.ts)
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';
import { AuthModule } from './auth/auth.module';

@Module({
  imports: [UsersModule, AuthModule],
})
export class AppModule {}

4.3 依赖注入

Nest.js依赖注入 提供者Provider 消费者Consumer 服务Service 存储库Repository 工厂Factory 辅助类Helper 控制器Controller 其他服务Service 守卫Guard 拦截器Interceptor

typescript 复制代码
// 定义提供者
@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
    this.cats.push(cat);
  }

  findAll(): Cat[] {
    return this.cats;
  }
}

// 注册提供者
@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}

// 消费依赖
@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}
  
  @Get()
  findAll() {
    return this.catsService.findAll();
  }
}

4.4 中间件、守卫和拦截器

客户端请求 中间件 守卫 拦截器-前 管道 控制器路由处理 拦截器-后 异常过滤器 响应

typescript 复制代码
// 中间件
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: Function) {
    console.log(`Request... ${req.method} ${req.url}`);
    next();
  }
}

// 使用中间件
@Module({
  imports: [UsersModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('users');
  }
}

// 守卫
@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    // 验证逻辑
    return isAuthorized(request);
  }
}

// 拦截器
@Injectable()
export class TransformInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('Before...');
    
    return next
      .handle()
      .pipe(
        map(data => {
          console.log('After...');
          return { data, timestamp: new Date().toISOString() };
        }),
      );
  }
}

// 管道
@Injectable()
export class ValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    // 数据验证和转换逻辑
    return validatedValue;
  }
}

5. Fastify

5.1 Fastify概述

Fastify是一个专注于性能和低开销的快速Web框架,提供了一套精简API,适合构建高性能的服务。
Fastify特点 高性能 低内存占用 插件架构 Schema验证 TypeScript支持 日志内置

5.2 基本用法

5.2.1 安装Fastify

bash 复制代码
npm install fastify

5.2.2 创建服务器

javascript 复制代码
const fastify = require('fastify')({ logger: true });
const port = 3000;

// 定义路由
fastify.get('/', async (request, reply) => {
  return { hello: 'world' };
});

// 启动服务器
const start = async () => {
  try {
    await fastify.listen({ port });
    fastify.log.info(`服务器运行在 ${fastify.server.address().port}`);
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};

start();

5.3 Schema验证和序列化

javascript 复制代码
// 定义带有Schema的路由
fastify.route({
  method: 'POST',
  url: '/users',
  schema: {
    body: {
      type: 'object',
      required: ['name', 'email'],
      properties: {
        name: { type: 'string' },
        email: { type: 'string', format: 'email' },
        age: { type: 'integer', minimum: 18 }
      }
    },
    response: {
      200: {
        type: 'object',
        properties: {
          id: { type: 'integer' },
          name: { type: 'string' },
          email: { type: 'string' }
        }
      }
    }
  },
  handler: async (request, reply) => {
    const { name, email, age } = request.body;
    // 处理创建用户的逻辑
    const user = { id: 1, name, email };
    return user;
  }
});

5.4 插件系统

javascript 复制代码
// 定义插件
const myPlugin = async (fastify, options) => {
  // 注册钩子
  fastify.addHook('onRequest', async (request, reply) => {
    request.log.info('请求已接收');
  });
  
  // 注册路由
  fastify.get('/plugin-route', async (request, reply) => {
    return { message: '这是插件路由' };
  });
  
  // 装饰fastify实例
  fastify.decorate('utility', function() {
    return 'utility value';
  });
  
  // 装饰请求
  fastify.decorateRequest('customProp', 'custom value');
};

// 注册插件
fastify.register(myPlugin, { pluginOption: 'value' });

// 使用插件功能
fastify.get('/use-plugin', async (request, reply) => {
  console.log(fastify.utility());
  console.log(request.customProp);
  return { success: true };
});

5.5 与Express和Koa性能对比

bar title Node.js框架性能对比(请求/秒) "Express" : 12000 "Koa" : 15000 "Fastify" : 30000 "Bare Node.js" : 35000

6. Next.js

6.1 Next.js概述

Next.js是一个React框架,用于构建服务器渲染、静态生成和客户端渲染的React应用。它提供了现代Web应用所需的所有功能,如路由、图像优化、API路由等。
Next.js特性 服务器渲染SSR 静态站点生成SSG 混合渲染模式 文件系统路由 API路由 图像优化 自动代码分割 TypeScript支持

6.2 基本用法

6.2.1 创建Next.js应用

bash 复制代码
npx create-next-app my-next-app
# 或
yarn create next-app my-next-app

6.2.2 页面和路由

javascript 复制代码
// pages/index.js - 主页
import Head from 'next/head';

export default function Home() {
  return (
    <div>
      <Head>
        <title>Next.js应用</title>
        <meta name="description" content="我的Next.js应用" />
      </Head>
      <main>
        <h1>欢迎来到Next.js!</h1>
      </main>
    </div>
  );
}

// pages/users/[id].js - 动态路由
import { useRouter } from 'next/router';

export default function User() {
  const router = useRouter();
  const { id } = router.query;

  return (
    <div>
      <h1>用户: {id}</h1>
    </div>
  );
}

// pages/about.js - 静态页面
export default function About() {
  return (
    <div>
      <h1>关于我们</h1>
      <p>这是关于页面的内容</p>
    </div>
  );
}

6.3 数据获取方法

Next.js数据获取 getServerSideProps getStaticProps getStaticPaths 客户端数据获取 每次请求运行
服务器端渲染SSR 构建时运行
静态站点生成SSG 指定动态路由
需要预渲染的路径 React钩子
SWR/React Query

javascript 复制代码
// 服务器端渲染示例 (SSR)
export async function getServerSideProps(context) {
  // 从服务器获取数据
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  // 将数据传递给页面组件
  return {
    props: { data }, // 作为props传递给页面
  };
}

// 静态生成示例 (SSG)
export async function getStaticProps() {
  // 在构建时获取数据
  const res = await fetch('https://api.example.com/static-data');
  const data = await res.json();

  return {
    props: { data },
    revalidate: 60, // 增量静态再生成 (ISR) - 每60秒更新
  };
}

// 静态路径示例
export async function getStaticPaths() {
  // 获取所有可能的路径
  const res = await fetch('https://api.example.com/users');
  const users = await res.json();
  
  // 为每个用户生成路径
  const paths = users.map((user) => ({
    params: { id: user.id.toString() },
  }));

  return {
    paths,
    fallback: 'blocking', // 或 true 或 false
  };
}

6.4 API路由

javascript 复制代码
// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'Hello World!' });
}

// pages/api/users/[id].js - 动态API路由
export default function handler(req, res) {
  const { id } = req.query;
  const { method } = req;

  switch (method) {
    case 'GET':
      // 获取用户
      res.status(200).json({ id, name: 'John Doe' });
      break;
    case 'PUT':
      // 更新用户
      res.status(200).json({ id, ...req.body });
      break;
    case 'DELETE':
      // 删除用户
      res.status(200).json({ id, deleted: true });
      break;
    default:
      res.setHeader('Allow', ['GET', 'PUT', 'DELETE']);
      res.status(405).end(`Method ${method} Not Allowed`);
  }
}

6.5 中间件和布局

javascript 复制代码
// middleware.js (Next.js 12+)
import { NextResponse } from 'next/server';

export function middleware(request) {
  // 检查身份验证
  const token = request.cookies.get('token');
  
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  
  return NextResponse.next();
}

// _app.js - 全局布局
import '../styles/globals.css';
import Layout from '../components/Layout';

function MyApp({ Component, pageProps }) {
  // 如果页面有自定义布局,使用它,否则使用默认布局
  const getLayout = Component.getLayout || ((page) => <Layout>{page}</Layout>);
  
  return getLayout(<Component {...pageProps} />);
}

export default MyApp;

// components/Layout.js
export default function Layout({ children }) {
  return (
    <>
      <header>网站头部</header>
      <main>{children}</main>
      <footer>网站底部</footer>
    </>
  );
}

7. Hapi.js

7.1 Hapi.js概述

Hapi.js是一个功能丰富的框架,专注于配置而非代码,旨在帮助开发者构建可扩展的API和服务。
Hapi.js特性 配置驱动开发 内置缓存 身份验证框架 状态管理 插件系统 请求验证

7.2 基本用法

7.2.1 安装Hapi

bash 复制代码
npm install @hapi/hapi

7.2.2 创建服务器

javascript 复制代码
const Hapi = require('@hapi/hapi');

const init = async () => {
    const server = Hapi.server({
        port: 3000,
        host: 'localhost'
    });

    // 定义路由
    server.route({
        method: 'GET',
        path: '/',
        handler: (request, h) => {
            return 'Hello World!';
        }
    });

    await server.start();
    console.log('服务器运行在 %s', server.info.uri);
};

process.on('unhandledRejection', (err) => {
    console.log(err);
    process.exit(1);
});

init();

7.3 路由和处理程序

javascript 复制代码
// 基本路由
server.route({
    method: 'GET',
    path: '/users/{id}',
    handler: (request, h) => {
        const id = request.params.id;
        return { id, name: 'John Doe' };
    }
});

// 使用路由选项
server.route({
    method: 'POST',
    path: '/users',
    options: {
        validate: {
            payload: Joi.object({
                name: Joi.string().min(3).required(),
                email: Joi.string().email().required()
            })
        },
        auth: 'jwt',
        tags: ['api', 'users'],
        description: '创建新用户'
    },
    handler: async (request, h) => {
        const user = await createUser(request.payload);
        return h.response(user).code(201);
    }
});

// 路由通配符和参数
server.route({
    method: 'GET',
    path: '/files/{param*}',
    handler: (request, h) => {
        const path = request.params.param || '';
        return `请求的文件路径: ${path}`;
    }
});

7.4 插件和扩展

javascript 复制代码
// 定义插件
const myPlugin = {
    name: 'myPlugin',
    version: '1.0.0',
    register: async function (server, options) {
        // 添加路由
        server.route({
            method: 'GET',
            path: '/plugin-route',
            handler: (request, h) => {
                return { plugin: 'myPlugin' };
            }
        });

        // 注册扩展点
        server.ext('onRequest', (request, h) => {
            request.app.requestTime = new Date().getTime();
            return h.continue;
        });

        // 添加方法
        server.method('calculateTax', (price) => {
            return price * 0.2;
        });
    }
};

// 注册插件
const init = async () => {
    const server = Hapi.server({ /* ... */ });
    
    await server.register({
        plugin: myPlugin,
        options: { /* 插件选项 */ }
    });
    
    // 使用插件提供的方法
    server.route({
        method: 'GET',
        path: '/tax/{price}',
        handler: (request, h) => {
            const price = parseFloat(request.params.price);
            const tax = server.methods.calculateTax(price);
            return { price, tax, total: price + tax };
        }
    });
    
    await server.start();
};

7.5 验证和认证

javascript 复制代码
// 安装依赖
// npm install @hapi/joi @hapi/basic @hapi/jwt

const Joi = require('@hapi/joi');
const Basic = require('@hapi/basic');
const JWT = require('@hapi/jwt');

const init = async () => {
    const server = Hapi.server({ /* ... */ });
    
    // 注册认证插件
    await server.register([Basic, JWT]);
    
    // 配置JWT认证策略
    server.auth.strategy('jwt', 'jwt', {
        keys: 'your-secret-key',
        verify: {
            aud: 'urn:audience:app',
            iss: 'urn:issuer:app',
            sub: false,
            maxAgeSec: 14400 // 4小时
        },
        validate: (artifacts, request, h) => {
            return {
                isValid: true,
                credentials: { user: artifacts.decoded.payload.user }
            };
        }
    });
    
    // 配置基本认证策略
    server.auth.strategy('simple', 'basic', {
        validate: async (request, username, password, h) => {
            // 验证逻辑
            const isValid = username === 'admin' && password === 'password';
            const credentials = { id: 1, name: username };
            
            return { isValid, credentials };
        }
    });
    
    // 设置默认认证策略
    server.auth.default('jwt');
    
    // 带有验证的路由
    server.route({
        method: 'POST',
        path: '/users',
        options: {
            auth: 'jwt',
            validate: {
                payload: Joi.object({
                    name: Joi.string().min(3).max(50).required(),
                    email: Joi.string().email().required(),
                    age: Joi.number().integer().min(18).required()
                }),
                query: Joi.object({
                    includeDetails: Joi.boolean().default(false)
                }),
                failAction: (request, h, err) => {
                    throw err; // 将验证错误返回给客户端
                }
            }
        },
        handler: async (request, h) => {
            // 处理创建用户的逻辑
            return { success: true };
        }
    });
    
    await server.start();
};

8. 全栈框架: AdonisJS和Sails.js

8.1 AdonisJS概述

AdonisJS是一个全栈MVC框架,提供开箱即用的ORM、身份验证、授权等功能,类似于Laravel(PHP)和Rails(Ruby)的开发体验。
AdonisJS特性 MVC架构 内置ORM 身份验证 ACL授权 验证器 命令行工具 WebSocket支持

8.2 AdonisJS基本用法

8.2.1 创建AdonisJS应用

bash 复制代码
npm init adonis-ts-app@latest my-app

8.2.2 AdonisJS应用结构

复制代码
my-app/
├── app/                   # 应用代码
│   ├── Controllers/       # 控制器
│   ├── Models/            # 数据模型
│   ├── Middleware/        # 中间件
│   ├── Validators/        # 验证器
│   └── Services/          # 服务
├── config/                # 配置文件
├── contracts/             # TypeScript接口定义
├── database/              # 数据库相关
│   ├── migrations/        # 数据库迁移
│   └── seeders/           # 数据种子
├── providers/             # 服务提供者
├── public/                # 静态资源
├── resources/             # 视图和其他资源
│   └── views/             # 视图模板
├── start/                 # 启动文件
│   ├── routes.ts          # 路由定义
│   ├── kernel.ts          # HTTP内核配置
│   └── events.ts          # 事件监听器
├── .env                   # 环境变量
└── server.ts              # 服务器启动文件

8.2.3 路由和控制器

typescript 复制代码
// start/routes.ts
import Route from '@ioc:Adonis/Core/Route'

Route.get('/', 'HomeController.index')
Route.get('/about', 'HomeController.about')

Route.group(() => {
  Route.get('/', 'PostsController.index')
  Route.post('/', 'PostsController.store').middleware('auth')
  Route.get('/:id', 'PostsController.show')
  Route.put('/:id', 'PostsController.update').middleware('auth')
  Route.delete('/:id', 'PostsController.destroy').middleware('auth')
}).prefix('/api/posts')

// app/Controllers/Http/PostsController.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Post from 'App/Models/Post'

export default class PostsController {
  public async index({ request, response }: HttpContextContract) {
    const page = request.input('page', 1)
    const limit = request.input('limit', 10)
    
    const posts = await Post.query().paginate(page, limit)
    return response.ok(posts)
  }
  
  public async store({ request, response, auth }: HttpContextContract) {
    const postData = request.only(['title', 'content'])
    
    const post = await Post.create({
      ...postData,
      userId: auth.user!.id
    })
    
    return response.created(post)
  }
  
  public async show({ params, response }: HttpContextContract) {
    const post = await Post.find(params.id)
    
    if (!post) {
      return response.notFound({ message: '文章未找到' })
    }
    
    return response.ok(post)
  }
}

8.3 Sails.js概述

Sails.js是一个基于Express的全栈MVC框架,专注于企业级应用开发,提供了自动生成REST API、实时WebSocket等功能。
Sails.js特性 MVC架构 自动生成API 实时WebSocket ORM/Waterline 自动路由 国际化支持 安全策略

8.4 Sails.js基本用法

8.4.1 创建Sails.js应用

bash 复制代码
npm install sails -g
sails new my-sails-app
cd my-sails-app
sails lift

8.4.2 模型和API

javascript 复制代码
// api/models/User.js
module.exports = {
  attributes: {
    name: {
      type: 'string',
      required: true
    },
    email: {
      type: 'string',
      required: true,
      unique: true,
      isEmail: true
    },
    posts: {
      collection: 'post',
      via: 'owner'
    }
  }
};

// api/models/Post.js
module.exports = {
  attributes: {
    title: {
      type: 'string',
      required: true
    },
    content: {
      type: 'string'
    },
    owner: {
      model: 'user'
    }
  }
};

// api/controllers/PostController.js
module.exports = {
  // 自定义动作
  featured: async function(req, res) {
    const featuredPosts = await Post.find({ isFeatured: true });
    return res.json(featuredPosts);
  },
  
  // 覆盖默认动作
  create: async function(req, res) {
    // 自定义创建逻辑
    try {
      const postData = req.body;
      postData.owner = req.session.userId;
      
      const newPost = await Post.create(postData).fetch();
      return res.status(201).json(newPost);
    } catch (err) {
      return res.serverError(err);
    }
  }
};

8.4.3 路由配置

javascript 复制代码
// config/routes.js
module.exports.routes = {
  // 自定义REST路由
  'GET /api/posts/featured': 'PostController.featured',
  
  // 蓝图API路由 (自动生成)
  'GET /api/posts': 'PostController.find',
  'GET /api/posts/:id': 'PostController.findOne',
  'POST /api/posts': 'PostController.create',
  'PATCH /api/posts/:id': 'PostController.update',
  'DELETE /api/posts/:id': 'PostController.destroy',
  
  // 视图路由
  'GET /': { view: 'pages/homepage' }
};

// config/blueprints.js
module.exports.blueprints = {
  // 启用/禁用 REST 路由
  rest: true,
  
  // 启用/禁用 CRUD 快捷方式
  shortcuts: false,
  
  // 启用/禁用 WebSocket 动作
  actions: false,
  
  // REST 前缀
  prefix: '/api'
};

9. 专业领域框架

9.1 Loopback - API框架

Loopback特性 API自动生成 OpenAPI规范 强大的ORM 关系管理 授权/认证 GraphQL支持

9.1.1 基本使用

bash 复制代码
npm install -g @loopback/cli
lb4 app my-api
typescript 复制代码
// 定义模型
import {Entity, model, property} from '@loopback/repository';

@model()
export class Product extends Entity {
  @property({
    type: 'number',
    id: true,
    generated: true,
  })
  id?: number;

  @property({
    type: 'string',
    required: true,
  })
  name: string;

  @property({
    type: 'number',
    required: true,
  })
  price: number;

  constructor(data?: Partial<Product>) {
    super(data);
  }
}

// 定义存储库
import {DefaultCrudRepository} from '@loopback/repository';
import {Product} from '../models';
import {DbDataSource} from '../datasources';
import {inject} from '@loopback/core';

export class ProductRepository extends DefaultCrudRepository<
  Product,
  typeof Product.prototype.id
> {
  constructor(@inject('datasources.db') dataSource: DbDataSource) {
    super(Product, dataSource);
  }
}

// 定义控制器
import {
  Count,
  CountSchema,
  Filter,
  FilterExcludingWhere,
  repository,
  Where,
} from '@loopback/repository';
import {
  post,
  param,
  get,
  getModelSchemaRef,
  patch,
  put,
  del,
  requestBody,
  response,
} from '@loopback/rest';
import {Product} from '../models';
import {ProductRepository} from '../repositories';

export class ProductController {
  constructor(
    @repository(ProductRepository)
    public productRepository : ProductRepository,
  ) {}

  @post('/products')
  @response(200, {
    description: 'Product model instance',
    content: {'application/json': {schema: getModelSchemaRef(Product)}},
  })
  async create(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(Product, {
            title: 'NewProduct',
            exclude: ['id'],
          }),
        },
      },
    })
    product: Omit<Product, 'id'>,
  ): Promise<Product> {
    return this.productRepository.create(product);
  }

  @get('/products/{id}')
  @response(200, {
    description: 'Product model instance',
    content: {
      'application/json': {
        schema: getModelSchemaRef(Product, {includeRelations: true}),
      },
    },
  })
  async findById(
    @param.path.number('id') id: number,
    @param.filter(Product, {exclude: 'where'}) filter?: FilterExcludingWhere<Product>
  ): Promise<Product> {
    return this.productRepository.findById(id, filter);
  }
}

9.2 Strapi - 内容管理框架

Strapi特性 无头CMS 自定义内容类型 管理面板 用户角色权限 插件系统 RESTful API GraphQL API

9.2.1 基本使用

bash 复制代码
npx create-strapi-app my-project
javascript 复制代码
// 自定义控制器
// ./src/api/article/controllers/custom.js
module.exports = {
  async featured(ctx) {
    try {
      const featuredArticles = await strapi.db.query('api::article.article').findMany({
        where: { featured: true },
        populate: ['cover', 'category', 'author'],
      });
      
      return featuredArticles;
    } catch (err) {
      ctx.body = err;
    }
  },
};

// 自定义路由
// ./src/api/article/routes/custom.js
module.exports = {
  routes: [
    {
      method: 'GET',
      path: '/articles/featured',
      handler: 'custom.featured',
      config: {
        policies: [],
        middlewares: [],
      },
    },
  ],
};

// 生命周期钩子
// ./src/api/article/content-types/article/lifecycles.js
module.exports = {
  beforeCreate(event) {
    const { data, where, select, populate } = event.params;
    
    // 自动生成slug
    if (data.title && !data.slug) {
      data.slug = slugify(data.title, { lower: true });
    }
  },
  
  afterCreate(event) {
    const { result, params } = event;
    
    // 发送通知
    console.log(`Created article: ${result.title}`);
  },
};

10. 框架选择指南与比较

10.1 框架特性对比

框架特性对比 性能 学习曲线 开发速度 TypeScript支持 社区支持 企业适用性 Fastify > Koa > Express > Nest > Adonis Express < Koa < Fastify < Nest < Adonis Adonis > Nest > Express > Koa > Fastify Nest > Adonis > Next > Express/Koa/Fastify Express > Next > Nest > Koa > Fastify > Adonis Nest > Adonis > Express > Fastify > Koa

10.2 适用场景选择

mindmap root((选择框架)) 微服务 Fastify Nest.js Express 企业应用 Nest.js Loopback Hapi.js API开发 Express Fastify Koa Loopback 全栈应用 Next.js AdonisJS Sails.js 内容平台 Strapi Next.js 实时应用 Sails.js Socket.io + Express

结语

感谢您的阅读!期待您的一键三连!欢迎指正!

相关推荐
橙子家1 小时前
简单介绍下 Vue 2.x 中的几种生命周期钩子(Lifecycle Hooks)
前端
优雅的落幕1 小时前
从零开始的抽奖系统创作(2)
java·服务器·前端
BillKu1 小时前
Vue3 scoped样式使用通配符 * 的影响分析
前端·javascript·vue.js
liangshanbo12152 小时前
CSS attr() 函数详解
前端·css
观无2 小时前
VsCode开发环境之Node.js离线部署
ide·vscode·node.js
sunbyte3 小时前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Hidden Search Widget (交互式搜索框)
前端·javascript·vue.js·ecmascript·tailwindcss
喜欢你的名字和你笑的样子3 小时前
前端跨域问题,后端解决方案
前端
Allen Bright3 小时前
【HTML-2】HTML 标题标签:构建网页结构的基础
前端·html
Dragon Wu3 小时前
Taro Error: chunk common [mini-css-extract-plugin]
前端·小程序·前端框架·react·taro
Dragon Wu3 小时前
Taro 安全区域
前端·小程序·前端框架·taro