与Express/Koa框架
Express/Koa框架概述
Express和Koa都是Node.js生态中流行的Web应用框架。Express以其简单、灵活著称,而Koa由Express团队开发,采用更现代的异步处理机制。两者都支持TypeScript开发,为构建服务器端应用提供了强大支持。
基本架构对比
Express采用传统的回调函数处理请求,中间件通过next()
函数控制流程:
import express from 'express';
const app = express();
app.use((req, res, next) => {
console.log('Middleware 1');
next();
});
app.get('/', (req, res) => {
res.send('Hello Express');
});
Koa则基于ES6的async/await语法,使用上下文对象封装请求和响应:
import Koa from 'koa';
const app = new Koa();
app.use(async (ctx, next) => {
console.log('Middleware 1');
await next();
});
app.use(async ctx => {
ctx.body = 'Hello Koa';
});
中间件机制差异
Express中间件是线性执行的,每个中间件必须显式调用next()
才能继续:
// Express中间件示例
app.use((req, res, next) => {
// 必须调用next()否则请求会挂起
if (req.path === '/admin') {
return res.status(403).end();
}
next();
});
Koa中间件形成洋葱模型,支持更灵活的流程控制:
// Koa中间件洋葱模型
app.use(async (ctx, next) => {
console.log('进入中间件1');
await next(); // 执行下游中间件
console.log('离开中间件1'); // 会等所有下游中间件执行完
});
app.use(async ctx => {
ctx.body = '响应内容';
});
路由系统实现
Express内置了基础路由功能:
const router = express.Router();
router.get('/users', (req, res) => {
res.json([{ id: 1, name: 'Alice' }]);
});
app.use('/api', router);
Koa需要配合koa-router等第三方库:
import Router from '@koa/router';
const router = new Router();
router.get('/users', ctx => {
ctx.body = [{ id: 1, name: 'Alice' }];
});
app.use(router.routes());
错误处理方式
Express通常使用错误优先回调:
app.get('/error', (req, res, next) => {
fs.readFile('/不存在的文件', (err, data) => {
if (err) return next(err);
res.send(data);
});
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('出错了!');
});
Koa利用async/await的try/catch机制:
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
ctx.status = err.status || 500;
ctx.body = { error: err.message };
}
});
router.get('/error', async ctx => {
throw new Error('测试错误');
});
请求上下文扩展
Express需要手动扩展请求对象:
declare global {
namespace Express {
interface Request {
user?: User;
}
}
}
app.use((req, res, next) => {
req.user = { id: 1, name: 'Alice' };
next();
});
Koa的上下文对象更易于扩展:
import { Context } from 'koa';
declare module 'koa' {
interface Context {
user: User;
}
}
app.use(async (ctx, next) => {
ctx.user = { id: 1, name: 'Alice' };
await next();
});
性能考量
Koa的轻量级设计通常表现更好:
// Koa基准测试示例
const Koa = require('koa');
const app = new Koa();
app.use(ctx => {
ctx.body = 'Hello World';
});
// Express基准测试示例
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World');
});
测试数据显示Koa在简单请求处理上比Express快约10-15%,主要得益于更精简的核心设计。
生态系统比较
Express拥有更丰富的中间件生态:
// Express常用中间件
app.use(require('body-parser').json());
app.use(require('helmet')());
app.use(require('cors')());
Koa中间件通常更现代化:
// Koa常用中间件
app.use(require('koa-bodyparser')());
app.use(require('koa-helmet')());
app.use(require('@koa/cors')());
TypeScript集成实践
Express项目典型配置:
// tsconfig.json
{
"compilerOptions": {
"target": "ES2018",
"module": "commonjs",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true
}
}
Koa项目推荐配置:
// tsconfig.json
{
"compilerOptions": {
"target": "ES2018",
"module": "commonjs",
"esModuleInterop": true,
"strict": true,
"noImplicitAny": false
}
}
实际项目结构示例
Express典型项目结构:
src/
├── controllers/
│ ├── user.controller.ts
├── middlewares/
│ ├── auth.middleware.ts
├── routes/
│ ├── user.route.ts
├── app.ts
Koa推荐项目结构:
src/
├── controllers/
│ ├── user.controller.ts
├── middlewares/
│ ├── error.middleware.ts
├── routers/
│ ├── user.router.ts
├── app.ts
数据库集成示例
Express集成Mongoose:
import mongoose from 'mongoose';
mongoose.connect('mongodb://localhost/test');
const UserSchema = new mongoose.Schema({
name: String
});
const User = mongoose.model('User', UserSchema);
app.get('/users', async (req, res) => {
const users = await User.find();
res.json(users);
});
Koa集成TypeORM:
import { createConnection } from 'typeorm';
createConnection().then(connection => {
const userRepository = connection.getRepository(User);
router.get('/users', async ctx => {
ctx.body = await userRepository.find();
});
});
部署注意事项
Express应用部署配置示例:
// PM2配置文件
module.exports = {
apps: [{
name: 'express-app',
script: './dist/app.js',
instances: 'max',
exec_mode: 'cluster'
}]
}
Koa应用部署优化:
// PM2配置文件
module.exports = {
apps: [{
name: 'koa-app',
script: './dist/app.js',
instances: 0, // 根据CPU核心数自动扩展
exec_mode: 'cluster',
max_memory_restart: '1G'
}]
}
现代前端集成
Express配合Webpack:
const webpack = require('webpack');
const middleware = require('webpack-dev-middleware');
const compiler = webpack(webpackConfig);
app.use(middleware(compiler));
Koa配合Vite:
import { createServer as createViteServer } from 'vite';
const vite = await createViteServer({
server: { middlewareMode: true }
});
app.use(vite.middlewares);
测试策略实现
Express单元测试示例:
import request from 'supertest';
describe('GET /users', () => {
it('should return user list', async () => {
const res = await request(app)
.get('/users')
.expect(200);
expect(res.body).toBeInstanceOf(Array);
});
});
Koa集成测试示例:
import test from 'ava';
import { createApp } from '../src/app';
test('GET /users', async t => {
const app = createApp();
const res = await app.inject({
method: 'GET',
url: '/users'
});
t.is(res.statusCode, 200);
t.true(Array.isArray(JSON.parse(res.payload)));
});
安全实践对比
Express安全中间件配置:
app.use(helmet());
app.use(cors({
origin: ['https://example.com']
}));
app.use(rateLimit({
windowMs: 15 * 60 * 1000,
max: 100
}));
Koa安全配置示例:
app.use(require('koa-helmet')());
app.use(require('@koa/cors')({
origin: ctx => {
const allowed = ['https://example.com'];
return allowed.includes(ctx.request.header.origin) ?
ctx.request.header.origin : '';
}
}));
微服务架构适配
Express作为微服务网关:
import { createProxyMiddleware } from 'http-proxy-middleware';
app.use('/api/users', createProxyMiddleware({
target: 'http://user-service:3000',
changeOrigin: true
}));
Koa实现API聚合:
router.get('/aggregated', async ctx => {
const [userRes, orderRes] = await Promise.all([
axios.get('http://user-service/users'),
axios.get('http://order-service/orders')
]);
ctx.body = {
users: userRes.data,
orders: orderRes.data
};
});
实时功能实现
Express配合Socket.io:
import { createServer } from 'http';
import { Server } from 'socket.io';
const httpServer = createServer(app);
const io = new Server(httpServer);
io.on('connection', socket => {
socket.on('chat message', msg => {
io.emit('chat message', msg);
});
});
Koa使用WebSockets:
import WebSocket from 'ws';
const wss = new WebSocket.Server({ server });
wss.on('connection', ws => {
ws.on('message', message => {
wss.clients.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});
日志系统集成
Express日志配置:
import morgan from 'morgan';
app.use(morgan('combined'));
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
next();
});
Koa结构化日志:
import koaLogger from 'koa-logger';
import { createLogger, format, transports } from 'winston';
const logger = createLogger({
transports: [new transports.Console()]
});
app.use(koaLogger(str => {
logger.info(str);
}));
配置管理方案
Express多环境配置:
import dotenv from 'dotenv';
dotenv.config({
path: `.env.${process.env.NODE_ENV || 'development'}`
});
app.set('port', process.env.PORT || 3000);
Koa配置中心集成:
import config from 'config';
interface AppConfig {
port: number;
db: {
host: string;
port: number;
};
}
const appConfig = config.get<AppConfig>('app');
app.listen(appConfig.port);
容器化部署
Express Dockerfile示例:
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "dist/app.js"]
Koa容器优化:
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["node", "--enable-source-maps", "dist/app.js"]
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:与Node.js后端开发
下一篇:与GraphQL配合