【Node.js】Web开发框架

在这里插入图片描述

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

在这里插入图片描述

正文

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

npm install express

2.2.2 创建基本服务器

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 路由

// 基本路由
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 中间件

请求
全局中间件
路由特定中间件
路由处理器
响应
// 内置中间件
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 请求和响应

// 请求对象(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

npm install koa

3.2.2 创建基本服务器

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 中间件和上下文

// 错误处理中间件
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

npm i -g @nestjs/cli
nest new project-name

4.2.2 主要组件

// 控制器 (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
// 定义提供者
@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 中间件、守卫和拦截器

客户端请求
中间件
守卫
拦截器-前
管道
控制器路由处理
拦截器-后
异常过滤器
响应
// 中间件
@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

npm install fastify

5.2.2 创建服务器

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验证和序列化

// 定义带有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 插件系统

// 定义插件
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应用

npx create-next-app my-next-app
# 或
yarn create next-app my-next-app

6.2.2 页面和路由

// 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
// 服务器端渲染示例 (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路由

// 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 中间件和布局

// 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

npm install @hapi/hapi

7.2.2 创建服务器

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 路由和处理程序

// 基本路由
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 插件和扩展

// 定义插件
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 验证和认证

// 安装依赖
// 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应用

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 路由和控制器

// 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应用

npm install sails -g
sails new my-sails-app
cd my-sails-app
sails lift

8.4.2 模型和API

// 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 路由配置

// 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 基本使用

npm install -g @loopback/cli
lb4 app my-api
// 定义模型
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 基本使用

npx create-strapi-app my-project
// 自定义控制器
// ./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

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Guiat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值