在 Node.js 开发中,Express 是最为流行和广泛使用的 Web 框架之一。然而,随着项目需求的变化,一些新的轻量级框架开始崭露头角,其中 @tinyhttp/app 作为一个后起之秀。本文将对比这两个框架,从应用的创建、路由定义、以及中间件的使用等方面进行详细分析,并帮助你更好地了解它们的异同。
什么是 Express?
Express 是一个基于 Node.js 的 Web 应用框架,提供了一组简洁且强大的 API,使得开发人员能够快速构建 Web 应用和 RESTful API。由于其极简的设计、灵活性和强大的社区支持,Express 成为了 Node.js 开发中的事实标准。
Express 特性
- 简单易用:提供了简洁的 API 进行路由、请求和响应处理。
- 中间件支持:通过中间件的机制,可以在请求处理的过程中处理各种逻辑。
- 强大的社区支持:丰富的文档和第三方中间件支持。
- 灵活的路由机制:支持 RESTful 风格的路由定义。
什么是 @tinyhttp/app?
@tinyhttp/app 是一个新兴的 Web 框架,它主打轻量、快速且简洁的设计。作为 Express 的一个"微型替代品",@tinyhttp/app 的核心思想是将最常用的功能提取出来,去掉一些不必要的复杂性,从而减少了框架本身的体积。该框架的设计灵感来源于 Express,但它并不包括 Express 的全部功能,更加适用于那些对性能和包体积要求高的应用。
@tinyhttp/app 特性
- 极简的框架设计:只有最基本的功能,体积更小,速度更快。
- 与 Express 高度兼容:@tinyhttp/app 的 API 与 Express 很相似,因此 Express 的开发者可以轻松上手。
- 开箱即用:内置一些基本的功能,比如路由和中间件的处理。
- 良好的性能:由于去除了 Express 中的一些冗余功能,性能更高。
Express 与 @tinyhttp/app 的对比
下面我们将通过几个常见的开发场景来对比 Express 和 @tinyhttp/app 的写法差异,帮助你了解这两个框架的异同。
1. 安装与项目初始化
Express 安装
首先,使用 npm
安装 Express:
bash
npm install express
创建一个简单的 Express 应用:
js
const express = require('express');
const app = express();
app.get('/getList', (req, res) => {
// res.send('hello world!')
const { id, name, description } = req.query;
// console.log('id', id)
let result = list.filter(item => {
if(name){
return item.name === name
}
if(description){
return item.description === description
}
})
if (name || description) {
console.log('result', result)
return sendResponse(res, {code: 200, msg: 'success', data: result})
}
if (id) {
const it = list.find(item => item.id === parseInt(id))
return sendResponse(res, {code: 200, msg: 'success', data: it})
}else{
return sendResponse(res, {code: 200, msg: 'success', data: list})
}
})
const storage = multer.diskStorage({
destination: (req, file, cb) =>{
const uploadPath = path.join(__dirname, 'uploads')
if (!fs.existsSync(uploadPath)) {
fs.mkdirSync(uploadPath)
}
cb(null,uploadPath) // 上传文件存储目录
},
filename: (req, file, cb) =>{
const suffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + suffix + path.extname(file.originalname));
}
})
const upload = multer({
storage,
limits: {
fileSize: 100* 1024* 1024,
files: 20
},
})
app.post('/upload',upload.array('files', 20), (req, res)=>{
if (!req.files) {
sendErrorResponse(res, {code: 450, msg: '文件不能为空'})
}
sendResponse(res, {code: 200, data: null})
})
app.listen(3000, () => {
console.log('服务运行在3000端口');
});
@tinyhttp/app 安装
同样地,使用 npm
安装 @tinyhttp/app
:
bash
npm install @tinyhttp/app
创建一个简单的 @tinyhttp/app 应用: 需要在package.json中添加配置 type: module,
js
import { App } from '@tinyhttp/app';
const app = new App();
// ESM 不支持直接使用__dirname
// 获取当前模块的 URL
const currentUrl = import.meta.url;
// 使用 URL 转换为文件路径
const __filename = new URL(currentUrl).pathname;
const __dirname = path.dirname(__filename);
app.get('/getList', (req, res) => {
const { id, name, description } = req.query;
// console.log('id', id)
let result = list.filter(item => {
if(name){
return item.name === name
}
if(description){
return item.description === description
}
})
if (name || description) {
console.log('result', result)
return sendResponse(res, {code: 200, msg: 'success', data: result})
}
if (id) {
const it = list.find(item => item.id === parseInt(id))
return sendResponse(res, {code: 200, msg: 'success', data: it})
}else{
return sendResponse(res, {code: 200, msg: 'success', data: list})
}
})
const storage = multer.diskStorage({
destination: (req, file, cb) =>{
const uploadPath = path.join(__dirname, 'uploads').substring(1)
// 或者使用 node@10.12.0版本中提供的fileURLToPath(uploadPath)就可以不使用substring()方法了
if (!fs.existsSync(uploadPath)) {
fs.mkdirSync(uploadPath)
}
cb(null,uploadPath) // 上传文件存储目录
},
filename: (req, file, cb) =>{
const suffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + suffix + path.extname(file.originalname));
}
})
const upload = multer({
storage,
limits: {
fileSize: 100* 1024* 1024,
files: 20
},
})
// 文件上传
app.post('/upload',upload.array('files', 20), (req, res)=>{
if (!req.files) {
sendErrorResponse(res, {code: 450, msg: '文件不能为空'})
}
sendResponse(res, {code: 200, data: null})
})
app.listen(3000, () => {
console.log('服务运行在3000端口');
});
2. 路由定义
Express 路由定义
在 Express 中,路由通常是通过 HTTP 方法(如 app.get
, app.post
)来定义的:
js
app.get('/users', (req, res) => {
res.json({ users: [] });
});
@tinyhttp/app 路由定义
@tinyhttp/app 的路由定义与 Express 非常相似,使用 app.get
, app.post
等方法:
js
app.get('/users', (req, res) => {
res.json({ users: [] });
});
3. 中间件使用
Express 中间件使用
Express 支持通过 app.use()
来注册中间件。中间件可以在请求和响应之间执行一些操作,例如身份验证、日志记录等:
js
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
app.use(express.json()); // 解析 JSON 请求体
app.get('/users', (req, res) => {
res.json({ users: [] });
});
@tinyhttp/app 中间件使用
在 @tinyhttp/app 中,中间件的使用方式和 Express 十分相似。你也可以通过 app.use()
来添加中间件:
js
// 日志中间件
const logger = function(req, res, next){
const {method, url} = req;
console.log(`server logger ${new Date().toISOString()} method:${method}- url:${url}`)
next()
}
app.use(logger)
app.use(jsonParser) // @tinyhttp/app没有提供json解析工具,需要自己编写中间件,express有提供,直接使用express.json()
app.get('/users', (req, res) => {
res.json({ users: [] });
});
4. 错误处理中间件
Express 错误处理中间件
在 Express 中,错误处理中间件的签名必须接受 4 个参数:err
, req
, res
, 和 next
。例如:
js
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something went wrong!');
});
@tinyhttp/app 错误处理中间件
在 @tinyhttp/app 中,错误处理也类似,只不过它的 API 设计更简洁。例如:
js
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something went wrong!');
});
5. 性能与体积
由于 @tinyhttp/app 是一个极简框架,去除了 Express 中的一些复杂功能,因此它的体积更小,性能也更高。具体来说:
- 体积:Express 比 @tinyhttp/app 要重得多。Express 本身的体积约为 3MB,而 @tinyhttp/app 的体积通常在 100KB 左右。
- 性能:由于 @tinyhttp/app 去除了许多 Express 中的特性,它的请求处理速度通常比 Express 快。
6. 扩展性与社区支持
-
Express:由于 Express 已经存在了多年,它有一个庞大的生态系统,提供了各种插件和扩展。你可以轻松地找到各种中间件、路由插件和其他第三方工具来扩展你的应用。
-
@tinyhttp/app:@tinyhttp/app 是一个较新的框架,虽然它与 Express 的 API 兼容,但它的社区支持和插件数量远不及 Express。
结论
选择 Express 的场景
- 庞大的项目:如果你需要一个稳定、成熟的框架来构建复杂的应用,Express 是一个更好的选择。
- 丰富的社区支持:Express 拥有一个庞大的生态系统,你可以利用社区提供的各种插件和中间件。
- 灵活性和功能性:Express 提供了丰富的功能和中间件支持,适合构建复杂的 API 和 Web 应用。
选择 @tinyhttp/app 的场景
- 轻量级应用:如果你只需要一个轻量级的 Web 框架,并且不需要 Express 中的一些高级功能,那么 @tinyhttp/app 是一个很好的选择。
- 性能和体积要求高的应用:如果你希望应用更加高效、体积更小,并且不需要 Express 所有的功能,那么 @tinyhttp/app 可能是一个理想的选择。
总结
Express 和 @tinyhttp/app 在很多方面是相似的,尤其是在 API 设计上。对于习惯于 Express 的开发者,迁移到 @tinyhttp/app 会非常容易。不过,Express 更加适用于功能复杂、需要广泛扩展的应用,而 @tinyhttp/app 则适合那些追求轻量级、高性能的场景。根据你的项目需求选择适合的框架,才能让开发更加高效、愉快。