Node.js Web 框架选型指南:从 Express 到 Hono 的约束式决策
Node.js Web 框架没有脱离场景的统一排名。Express、NestJS、AdonisJS 和 Hono 解决的并不是同一个问题:有的提供最小 HTTP 组织能力,有的提供应用结构,有的连认证、ORM 和脚手架也一起提供,还有的优先适配 Web Standards 与多运行时。
因此,选型不能从“哪个框架最好”开始,而要先固定运行环境、团队能力和业务切片,再比较每个候选方案需要团队自行补齐什么。
一、先固定比较基线
本文使用 2026-08-18 的 npm 最新版本快照。版本会继续变化,读者应在正式选型时重新执行 npm view <package> version engines,并复核对应版本的迁移指南。
为了让八个候选方案能够进入同一轮 Node.js 验证,Node 侧 PoC 使用以下统一输入:
- 运行时:Node.js 24。
- 应用类型:TypeScript REST API。
- 业务切片:健康检查、带参数校验的写接口、鉴权中间件、统一错误映射、结构化日志。
- 交付约束:容器部署、可接入现有监控、能够编写契约测试。
- 评价维度:运行环境、框架抽象、内置能力、类型边界、团队迁移成本。
性能边界
本文没有执行八框架性能基准,因此不提供吞吐量排名。Fastify 和 Hono 的官方材料都强调性能,但官方定位不能替代项目数据。只有在相同硬件、Node.js 版本、路由、校验、日志和负载工具下取得的数据,才能进入最终性能决策。
如果目标环境是 Cloudflare Workers、Deno 或 Bun,应另建多运行时 PoC。把 Edge 运行时结果和常驻 Node.js 进程结果放在同一张吞吐表里,会混入部署模型差异。
二、候选版本与官方边界
下表中的版本和 Node.js 下限来自对应 npm 包元数据;Fastify v5 的 Node.js 下限来自官方迁移指南。Node.js 下限只是安装约束,不代表生产环境推荐版本。
| 框架 | 本文快照 | Node.js 下限 | 官方设计边界 |
|---|---|---|---|
| Express | 5.2.1 | >=18 | 官方将其定义为 minimal、unopinionated 框架,核心围绕路由与中间件 |
| Koa | 3.2.1 | >=18 | 官方首页强调 async 函数和更小的核心,并明确核心不捆绑中间件 |
| Fastify | 5.12.0 | >=20 | v5 迁移指南要求 Node.js 20+;框架提供插件封装以及 JSON Schema 校验和序列化 |
| NestJS | @nestjs/core 11.2.1 | >=20 | Modules 与 Providers/依赖注入构成主要应用结构,并通过 HTTP adapter 使用 Express 或 Fastify |
| hapi | @hapi/hapi 21.4.10 | >=14.15 | 官方站点围绕 Server、Route、请求生命周期和插件组织 HTTP 服务 |
| AdonisJS | @adonisjs/core 7.4.0 | >=24 | 官方介绍将其定义为 backend-first、type-safe 框架,并提供认证、校验、ORM 等常用后端能力 |
| Egg | 3.34.0 | >=14.20 | 官方站点以 Koa 为基础,通过约定、配置和插件体系组织企业应用 |
| Hono | 4.13.2 | >=16.9(npm 包) | 官方设计说明基于 Web Standards,覆盖 Node.js、Cloudflare Workers、Deno、Bun 等运行时 |
这八个候选可以分成四类,但分类只描述边界,不代表高低:
- 最小核心:Express、Koa。
- API 与插件内核:Fastify、hapi。
- 应用级框架:NestJS、AdonisJS、Egg。
- 多运行时 Web Standards:Hono。
三、在同一约束下比较
3.1 结构与能力矩阵
下表只比较可由官方文档确认的设计边界。团队熟悉度、招聘成本和现有中间件兼容性必须由项目自己的代码库与人员情况补充。
| 框架 | 主要组织方式 | 框架负责的范围 | 团队需要重点补齐 |
|---|---|---|---|
| Express | 路由与中间件链 | 最小 HTTP 应用骨架 | 目录规范、校验、错误约定、依赖组织 |
| Koa | async 洋葱中间件 | Context 与中间件执行模型 | 路由、校验、应用分层和配套组件选择 |
| Fastify | 插件封装、Hook、Schema | API 内核、校验与序列化边界 | 统一插件封装、Schema/类型同步、生态适配 |
| NestJS | Module、Controller、Provider | 依赖注入和模块化应用结构 | 装饰器与 DI 心智模型、模块边界治理 |
| hapi | Server、Route 配置、生命周期扩展点、Plugin | 服务器生命周期与插件化 HTTP 能力 | 应用分层、类型约定和团队目录规范 |
| AdonisJS | MVC 与框架约定 | 路由、校验、认证、ORM 等后端常用能力 | 接受框架约定,管理框架内外组件边界 |
| Egg | 目录约定、配置、插件 | Koa 之上的企业应用组织方式 | 理解加载约定,维护内部插件与配置体系 |
| Hono | Web Standards API、路由与中间件 | 轻量 Web API 与多运行时适配 | 按目标运行时选择数据库、文件系统和可观测性方案 |
3.2 不能从表格直接推出的结论
结构矩阵不能直接回答三个问题:
- 谁的吞吐量最高。这个问题需要相同业务切片下的测量结果。
- 谁的学习成本最低。团队已有经验会改变结论。
- 谁的生态最大。项目真正依赖的是一组具体组件,而不是抽象的包数量。
因此,选型文章可以帮助缩小候选范围,但不能替团队完成 PoC。
四、让八个候选都进入决策路径
下面的流程图先判断部署环境,再判断团队希望框架承担多少应用结构。每个候选都有明确的进入条件。
4.1 每条路径的适用与退出条件
| 选择 | 适用条件 | 不适用信号 |
|---|---|---|
| Express | 团队已有 Express 中间件与维护经验,希望保留最小框架约束 | 项目需要框架统一模块、依赖和目录边界 |
| Koa | 团队明确需要 async 洋葱模型,并能自行选择路由、校验和分层方案 | 团队希望开箱即用的应用规范 |
| Fastify | API 契约以 JSON Schema 为核心,希望用插件封装能力边界 | 团队不准备维护 Schema、类型和响应契约的一致性 |
| NestJS | 多团队需要统一 Module/Provider 边界,并接受 DI 与装饰器体系 | 项目很小,或团队不希望引入应用级抽象 |
| hapi | 团队偏好显式 Route 配置、请求生命周期扩展点和 Server Plugin | 现有资产主要围绕 Express/Koa 中间件 |
| AdonisJS | 项目需要完整后端能力,并愿意采用框架约定与 Node.js 24 | 只需要轻量 API,或必须保留多框架组件自由度 |
| Egg | 团队已有 Egg/Koa 企业应用经验、内部插件或配置资产 | 新团队没有这些资产,也不需要 Egg 的加载与约定体系 |
| Hono | 目标包含 Workers、Deno、Bun 等运行时,业务可以围绕 Web Standards API 设计 | 强依赖 Node.js 专属中间件或文件系统能力 |
这里没有“Fastify 一定比 Express 快”或“Hono 是 Edge 的唯一选择”这样的结论。正确表达是:这些框架的设计约束不同,候选方案必须先满足部署和组织边界,性能再由同基准 PoC 决定。
五、代价与风险
框架替团队完成的事情越多,团队需要接受的框架约定通常也越多。以下风险应在 PoC 中逐项验证。
| 选择 | 主要代价 | PoC 重点 |
|---|---|---|
| Express | 关键工程规范需要团队自行制定 | 错误处理、校验、日志和目录规范能否统一 |
| Koa | 配套组件需要自行选择和维护 | 路由、异常链路和异步上下文是否稳定 |
| Fastify | Schema 和插件封装会成为长期资产 | 类型、校验、序列化是否保持同源 |
| NestJS | DI、装饰器和模块边界增加概念数量 | 跨模块依赖是否清晰,测试替身是否易维护 |
| hapi | 配置与生命周期模型需要团队统一理解 | 插件边界、错误映射和现有组件集成 |
| AdonisJS | 应用与框架提供的完整能力绑定更深 | ORM、认证和框架升级的迁移成本 |
| Egg | 目录约定、加载顺序和内部插件形成平台资产 | 新成员理解成本和现有 Koa 组件复用方式 |
| Hono | 多运行时差异会落到外部依赖和部署适配层 | 数据库、文件、日志、追踪在目标运行时是否可用 |
六、用真实业务切片完成决策
6.1 第一轮:约束淘汰
先用硬约束淘汰不满足条件的框架:
- 检查 Node.js 或 Edge 运行时要求。
- 列出现有中间件、ORM、认证和可观测性依赖。
- 确认团队是否接受 DI、MVC、Schema 或目录约定。
- 将候选范围缩小到两个,最多三个。
6.2 第二轮:同切片 PoC
每个候选都实现同一组接口,并保持以下条件一致:
- 相同 Node.js 版本、容器资源和启动参数。
- 相同请求与响应 JSON Schema。
- 相同鉴权、日志、错误映射和数据库模拟层。
- 相同负载工具、并发梯度、预热时间和采样时间。
- 同时记录实现时间、依赖数量、冷启动、P95 延迟、吞吐量和内存。
如果候选包含 Hono 的 Edge 部署,需要在目标 Edge 平台另跑一轮。该结果只和同平台实现比较,不与本地常驻 Node.js 进程直接合并。
6.3 第三轮:保留回滚路径
PoC 阶段不要直接迁移整套业务。先保留以下回滚边界:
- 用契约测试固定 HTTP 行为。
- 把框架专属对象限制在入口、路由和适配层。
- 先迁移一个可独立回退的业务切片。
- 记录框架专属插件、装饰器、Schema 和 ORM 用法。
- 在监控、错误处理和部署验证通过前,不扩大迁移范围。
七、总结
Node.js Web 框架选型不是把八个名字排成一列,而是依次回答三个问题:目标运行在哪里,框架需要替团队承担多少结构,团队愿意维护哪些长期约束。
Express 和 Koa 保留更多组装权;Fastify 与 hapi 提供更明确的 API 或服务器生命周期模型;NestJS、AdonisJS 和 Egg 提供应用级结构;Hono 把 Web Standards 与多运行时放在首要位置。
先用硬约束缩小范围,再用统一业务切片产生项目自己的证据。只有完成这两步,“最合适”才是工程结论,而不是框架印象。
