快速且低开销的 Node.js Web 框架
初衷
高效的服务器意味着较低的基础设施成本、更好的负载响应能力、以及满意的用户。 在知道你正在服务尽可能多的请求的情况下,如何有效地处理服务器资源,而不牺牲安全验证和方便的开发?
进入 Fastify。 Fastify 是一个 Web 框架,高度专注于以最少的开销和强大的插件架构提供最佳的开发者体验。 它的灵感来自 Hapi 和 Express,据我们所知,它是最快的 Web 框架之一。
核心特性
以下是 Fastify 构建的主要特性和原则:
- 高性能: 据我们所知,Fastify 是最快的 Web 框架之一,根据代码复杂性,我们每秒可以处理高达 30,000 个请求。
- 可扩展: Fastify 通过其钩子、插件和装饰器是完全可扩展的。
- 基于结构: 即使不是强制性的,我们也建议使用 JSON 结构 来验证你的路由并序列化你的输出,Fastify 在内部以高性能函数编译结构。
- 日志记录: 日志极其重要,但成本高昂; 我们选择了最好的日志器来几乎消除这个成本,Pino!
- 开发者友好: 该框架的构建非常具有表现力,可以帮助开发者日常使用,而不会牺牲性能和安全性。
- TypeScript 就绪: 我们努力维护 TypeScript 类型声明文件,以便支持不断发展的 TypeScript 社区。
快速开始
使用 NPM 获取 Fastify:
npm install fastify
然后创建 server.js
并添加以下内容:
- ESM
- CJS
// Import the framework and instantiate it
import Fastify from 'fastify'
const fastify = Fastify({
logger: true
})
// Declare a route
fastify.get('/', async function handler (request, reply) {
return { hello: 'world' }
})
// Run the server!
try {
await fastify.listen({ port: 3000 })
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
// Require the framework and instantiate it
const fastify = require('fastify')({ logger: true })
// Declare a route
fastify.get('/', function handler (request, reply) {
reply.send({ hello: 'world' })
})
// Run the server!
fastify.listen({ port: 3000 }, (err) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
最后,使用以下方法启动服务器:
node server
并用以下方法测试它:
curl http://localhost:3000
使用 CLI
获取 fastify-cli 来创建一个新的脚手架项目:
npm install --global fastify-cli
fastify generate myproject
请求/响应校验和钩子
Fastify 能做的远不止这些。 例如,你可以使用 JSON Schema 轻松提供输入和输出校验,并在执行处理程序之前执行特定操作:
- ESM
- CJS
import Fastify from 'fastify'
const fastify = Fastify({
logger: true
})
fastify.route({
method: 'GET',
url: '/',
schema: {
// request needs to have a querystring with a `name` parameter
querystring: {
type: 'object',
properties: {
name: { type: 'string'}
},
required: ['name'],
},
// the response needs to be an object with an `hello` property of type 'string'
response: {
200: {
type: 'object',
properties: {
hello: { type: 'string' }
}
}
}
},
// this function is executed for every request before the handler is executed
preHandler: async (request, reply) => {
// E.g. check authentication
},
handler: async (request, reply) => {
return { hello: 'world' }
}
})
try {
await fastify.listen({ port: 3000 })
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
const fastify = require('fastify')({ logger: true })
fastify.route({
method: 'GET',
url: '/',
schema: {
// request needs to have a querystring with a `name` parameter
querystring: {
type: 'object',
properties: {
name: { type: 'string'}
},
required: ['name'],
},
// the response needs to be an object with an `hello` property of type 'string'
response: {
200: {
type: 'object',
properties: {
hello: { type: 'string' }
}
}
}
},
// this function is executed for every request before the handler is executed
preHandler: (request, reply, done) => {
// E.g. check authentication
done()
},
handler: (request, reply) => {
reply.send({ hello: 'world' })
}
})
fastify.listen({ port: 3000 }, (err) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
TypeScript 支持
Fastify 附带了一个类型文件,但你可能需要安装 @types/node
,具体取决于你使用的 Node.js 版本。
以下示例创建一个 http 服务器。
我们传入我们使用的 http 版本的相关类型。 通过传入类型,我们可以获得对路由中底层 http 对象的正确类型访问。
如果使用 http2,我们将传入 <http2.Http2Server, http2.Http2ServerRequest, http2.Http2ServerResponse>
。
对于 https,传入 http2.Http2SecureServer
或 http.SecureServer
而不是 Server。
这确保了在服务器处理程序中我们也能获得 http.ServerResponse
,并在 reply.res
上输入正确的内容。
- TypeScript
import Fastify, { FastifyInstance, RouteShorthandOptions } from 'fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'
const server: FastifyInstance = Fastify({})
const opts: RouteShorthandOptions = {
schema: {
response: {
200: {
type: 'object',
properties: {
pong: {
type: 'string'
}
}
}
}
}
}
server.get('/ping', opts, async (request, reply) => {
return { pong: 'it worked!' }
})
const start = async () => {
try {
await server.listen({ port: 3000 })
const address = server.server.address()
const port = typeof address === 'string' ? address : address?.port
} catch (err) {
server.log.error(err)
process.exit(1)
}
}
start()
请访问 文档 以了解有关 Fastify 提供的所有功能的更多信息。