@karinjs/express
v1.1.4
Published
Fast, unopinionated, minimalist web framework
Readme
@karinjs/express
基于 TypeScript 重写的 Express 5.x 框架
快速、极简、无约束的 Web 框架
English | 简体中文
📖 项目简介
这是一个完全使用 TypeScript 重写的 Express 5.x 框架,旨在提供更好的类型安全性和开发体验,同时保持与原版 Express 的 API 兼容性。
🎯 项目初衷
本项目专为 github.com/karinjs/karin 优化而开发,针对其特定使用场景进行了深度定制和性能优化。
⚠️ 特别声明
[!WARNING] 本项目未经生产环境充分验证,不建议非专业用户使用。
- 🔴 本项目仍在积极开发中
- 🔴 未经过大规模生产环境的长期验证
- 🔴 建议仅在开发和测试环境中使用
- 🔴 生产环境使用需自行承担风险
📋 免责声明
- 本项目按 "原样" 提供,不提供任何明示或暗示的保证
- 使用本项目所产生的任何直接或间接损失,开发者不承担责任
- 本项目基于 Express 5.x 进行重写,但与官方 Express 项目无关
- 在生产环境使用前,请进行充分的测试和评估
- 对于关键业务系统,建议使用经过验证的稳定版本(如官方 Express)
✨ 主要特性
- 🎯 完整的 TypeScript 重写:核心代码全部使用 TypeScript 编写
- 🔒 类型安全:提供完整的类型定义,享受更好的 IDE 智能提示
- 📦 Monorepo 架构:使用 pnpm workspace 管理多个相关包
- 🚀 现代化构建:使用 tsdown 进行高效打包
- ⚡ ESM 优先:原生支持 ES Modules
- 🔄 API 兼容:保持与 Express 5.x 的 API 兼容性
- 🧪 完整测试:包含大量单元测试和集成测试
🏗️ 项目架构
Monorepo 结构
本项目采用 pnpm workspace 管理,包含以下子包:
packages:
- "packages/path-to-regexp" # 路径匹配和参数提取
- "packages/send" # 文件发送类型定义
- "packages/connect" # Connect 中间件类型定义
- "packages/serve-static" # 静态文件服务核心模块
src/
├── application.ts # Application 类 - 核心应用逻辑
├── express.ts # Express 工厂函数和导出
├── request.ts # Request 类 - 扩展的请求对象
├── response.ts # Response 类 - 扩展的响应对象
├── view.ts # 视图渲染系统
├── utils.ts # 工具函数
├── router/ # 路由系统
│ ├── index.ts # Router 类
│ ├── layer.ts # 路由层
│ └── route.ts # Route 类
├── body-parser/ # 请求体解析器
│ └── src/
└── serve-static/ # 静态文件服务实现
└── index.ts🔄 与原版 Express 的主要区别
1. 完全的 TypeScript 实现
- 原版:JavaScript 实现,通过
@types/express提供类型 - 本项目:TypeScript 原生实现,类型定义即源码
// 更好的类型推导
const app = express()
app.get('/user/:id', (req, res) => {
// req.params 自动推导类型
const id = req.params.id // string
res.json({ id })
})2. 模块化架构
- 原版:依赖外部 npm 包(如
path-to-regexp、send等) - 本项目:将核心依赖纳入 monorepo,便于维护和定制
3. 现代化的构建系统
- 原版:传统的 CommonJS 模块
- 本项目:
- 使用
tsdown构建,生成 ESM 格式 - 支持 Tree-shaking
- 更小的包体积
- 使用
// tsdown.config.ts
export default defineConfig({
entry: ['./src/index.ts'],
format: ['esm'],
dts: { resolve: true, build: true },
target: 'node18',
platform: 'node',
})4. 增强的类型系统
- Application 类:完整的类型定义,包括所有 HTTP 方法
- Request/Response:泛型支持,更精确的类型推导
- 路由系统:路径参数、查询参数的类型安全
// 泛型支持示例
class Request<
P = ParamsDictionary, // 路径参数类型
ResBody = any, // 响应体类型
ReqBody = any, // 请求体类型
ReqQuery = ParsedQs, // 查询参数类型
LocalsObj = Record<string, any> // 本地变量类型
> extends IncomingMessage5. 内置模块重写
Router 模块
- 完全 TypeScript 重写
- 更好的路由匹配性能
- 类型安全的中间件链
Body Parser
- 集成到核心,无需单独安装
- TypeScript 原生实现
- 支持 JSON、URL-encoded、Raw、Text 等格式
Serve Static
- 静态文件服务的 TypeScript 实现
- 更好的错误处理
- 内置安全特性
6. 改进的错误处理
// Application.status() - 更严格的状态码验证
status(code: StatusCode): this {
if (!Number.isInteger(code)) {
throw new TypeError(`Invalid status code: ${JSON.stringify(code)}`)
}
if (code < 100 || code > 999) {
throw new RangeError(`Invalid status code: ${JSON.stringify(code)}`)
}
this.statusCode = code
return this
}7. 优化的开发体验
- 路径别名配置:
{
"paths": {
"router": ["./src/router/index.ts"],
"body-parser": ["./src/body-parser/src/index.ts"],
"serve-static": ["./src/serve-static/index.ts"]
}
}- 统一的测试框架:所有模块使用 Mocha + TypeScript
- 现代化的工具链:ESLint、TypeScript 5.x
📦 安装
npm install @karinjs/express
# 或
pnpm add @karinjs/express
# 或
yarn add @karinjs/express🚀 快速开始
import express from '@karinjs/express'
const app = express()
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000')
})💡 核心改进点
1. 类型安全的中间件
import { RequestHandler } from '@karinjs/express'
const authMiddleware: RequestHandler = (req, res, next) => {
// 完整的类型提示
const token = req.get('Authorization')
if (!token) {
return res.status(401).json({ error: 'Unauthorized' })
}
next()
}2. 泛型路由处理
interface UserParams {
id: string
}
interface UserBody {
name: string
email: string
}
app.post<UserParams, any, UserBody>('/user/:id', (req, res) => {
const { id } = req.params // 类型: { id: string }
const { name, email } = req.body // 类型: { name: string, email: string }
res.json({ id, name, email })
})3. 内置 Body Parser
// 无需额外安装 body-parser
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.post('/api/data', (req, res) => {
console.log(req.body) // 自动解析
res.json({ received: true })
})4. 静态文件服务
// 使用内置的 serve-static
app.use(express.static('public'))
app.use('/static', express.static('assets'))📚 API 文档
本项目保持与 Express 5.x 的 API 兼容性。主要的 API 包括:
Application
app.get(path, ...handlers)app.post(path, ...handlers)app.put(path, ...handlers)app.delete(path, ...handlers)app.use([path], ...middleware)app.listen(port, [callback])app.set(setting, value)app.engine(ext, callback)app.render(view, [locals], callback)
Request
req.params- 路径参数req.query- 查询参数req.body- 请求体req.get(field)- 获取请求头req.accepts(types)- 内容协商req.is(type)- 检查 Content-Type
Response
res.status(code)- 设置状态码res.send(body)- 发送响应res.json(obj)- 发送 JSONres.redirect([status], url)- 重定向res.render(view, [locals], [callback])- 渲染视图res.sendFile(path, [options], [callback])- 发送文件
🧪 测试
# 运行所有测试
pnpm test
# 运行特定模块测试
pnpm test:router
pnpm test:body-parser
pnpm test:serve-static
# 运行验收测试
pnpm test:acceptance
# 生成覆盖率报告
pnpm test-cov🛠️ 开发
# 克隆仓库
git clone https://github.com/sj817/express.git
cd express
# 安装依赖
pnpm install
# 构建项目
pnpm build
# 运行 Lint
pnpm lint
# 修复 Lint 问题
pnpm lint:fix📋 为什么要重写?
1. 类型安全
原版 Express 的类型定义存在于 @types/express,与实现分离,容易出现类型不匹配的问题。TypeScript 原生实现可以确保类型与代码完全一致。
2. 更好的维护性
Monorepo 架构使得核心依赖都在一个仓库中,便于整体维护和优化,减少版本不兼容的风险。
3. 现代化特性
- 原生 ESM 支持
- 更小的包体积(Tree-shaking)
- 更好的构建性能(tsdown)
4. 学习和定制
完全掌握代码实现,方便根据项目需求进行定制和优化。
5. 性能优化
- 减少依赖层级
- 优化的路由匹配算法
- 更高效的类型推导
🎯 项目目标
- ✅ 完整的 TypeScript 重写
- ✅ 保持 API 兼容性
- ✅ Monorepo 架构
- ✅ 完整的测试覆盖
- ✅ 现代化构建系统
- 🚧 性能优化
- 🚧 更多示例和文档
📄 许可证
🤝 贡献
欢迎提交 Issue 和 Pull Request!
📦 打包产物
本项目使用 tsdown 进行打包,最终产物为零依赖的纯 ESM 模块:
✨ 打包产物信息:
ℹ dist/index.mjs 904.62 kB │ gzip: 278.74 kB
ℹ dist/index.d.ts 75.65 kB │ gzip: 20.25 kB
ℹ 2 files, total: 980.27 kB
📊 对比数据:
源包大小: 2.2MB / 65 packages (数据来源: https://pkg-size.dev/express)
打包后: 980.27 kB / 0 dependencies ⚡🎯 零依赖优势
打包后的代码完全独立运行,无需安装任何额外依赖:
- ✅ 部署简单:无需担心依赖版本冲突
- ✅ 体积更小:打包后仅 980 KB(压缩后 278 KB)
- ✅ 安全可靠:减少供应链攻击风险
- ✅ 性能优化:减少模块加载开销
🚀 ESM 现代化
由于采用 ESM 格式,代码可完全参与任何现代化打包器的优化:
- 🌲 Tree-shaking:自动移除未使用的代码
- 📦 打包器友好:完美支持 Vite、Rollup、esbuild、webpack 等
- 🔒 类型完整:包含完整的 TypeScript 类型定义
- ⚡ 按需加载:支持动态 import 和代码分割
妈妈再也不用担心打包器无法处理 Express 啦! 🎉
🙏 致谢
本项目基于 Express 进行重写,感谢 Express 团队及所有贡献者的杰出工作。
上游核心依赖
本项目将以下核心依赖整合到 Monorepo 中,并进行了 TypeScript 重写:
路由与中间件
- path-to-regexp (v8.3.0) - 路径匹配和参数提取
- router (v2.2.0) - HTTP 路由系统
- @types/connect (v3.4.38) - Connect 中间件类型定义
静态文件服务
- serve-static (v2.2.0) - 静态文件服务
- @types/send (v1.2.1) - 文件发送类型定义
请求体解析
- body-parser - 请求体解析器(已整合重写)
- JSON 解析
- URL-encoded 解析
- Raw 解析
- Text 解析
运行时依赖库
以下依赖库在打包时被内联,最终产物为零依赖:
HTTP 工具
- accepts - 内容协商
- content-disposition - Content-Disposition 头处理
- content-type - Content-Type 解析
- cookie - Cookie 解析和序列化
- cookie-signature - Cookie 签名
- encodeurl - URL 编码
- escape-html - HTML 转义
- etag - ETag 生成
- fresh - HTTP 缓存验证
- http-errors - HTTP 错误创建
- merge-descriptors - 对象属性合并
- methods - HTTP 方法列表
- mime-types - MIME 类型解析
- on-finished - HTTP 响应完成检测
- parseurl - URL 解析
- proxy-addr - 代理地址解析
- qs - 查询字符串解析(使用 @karinjs/qs)
- range-parser - Range 头解析
- safe-buffer - 安全的 Buffer API
- send - 文件发送
- statuses - HTTP 状态码
- type-is - Content-Type 检测
- vary - Vary 头处理
工具库
- bytes - 字节大小解析
- debug - 调试工具
- depd - 弃用警告
- finalhandler - 最终请求处理器
- iconv-lite - 字符编码转换
- raw-body - 原始请求体读取
开发工具
构建与类型
- TypeScript (v5.9.3) - TypeScript 编译器
- tsdown (v0.16.7) - 高性能 TypeScript 打包工具
- tsx - TypeScript 执行器
测试框架
代码质量
- ESLint - 代码检查工具
- neostandard - 现代 JavaScript 标准
- depcheck - 依赖检查工具
特别感谢
- TJ Holowaychuk - Express 和众多 Node.js 生态库的创始人
- Douglas Wilson - Express 核心维护者
- Express 团队 - 维护 Express 及相关生态
- jshttp 组织 - 提供众多 HTTP 工具库
- pillarjs 组织 - 提供路由和中间件基础设施
📮 联系方式
- GitHub: sj817/express
- npm: @karinjs/express
如果这个项目对你有帮助,请给一个 ⭐️ Star 支持一下!
