Fastify,快速并且低开销的 web 框架,专为 Node.js 平台量身打造

为什么选择 Fastify?

高效的服务器意味着更低的基础设施成本、更好的负载响应能力和用户满意度。 在不牺牲安全验证和便捷开发的前提下,如何知道服务器正在处理尽可能多的请求,又如何有效地处理服务器资源?

使用 Fastify 吧。 Fastify 是一个高度专注于以最少的开销和强大的插件架构为开发人员提供最佳开发体验的 Web 框架。 Fastify 受到 Hapi 和 Express 框架的启发。据我们所知,Fastify 是我们村最快的 web 框架之一,也是我们“全村的希望”!

Fastify 用户列表

Fastify 正在为大型机构和产品生态提供助力。

这里列出了更多使用 Fastify 的机构。你所在的机构也可以展示在这个列表里

  • Mr Porter is using Fastify
  • RuneAudio is using Fastify
  • Commons Host is using Fastify
  • Vectra is using Fastify
  • Nucleode is using Fastify
  • Radity is using Fastify

核心功能

以下列出的是 Fastify 已经实现的主要功能及原理:

  • 高性能: 据我们所知,Fastify 是这一领域中最快的 web 框架之一,另外,取决于代码的复杂性,Fastify 最多可以处理每秒 3 万次的请求。
  • 可扩展: Fastify 通过其提供的钩子(hook)、插件和装饰器(decorator)提供完整的可扩展性。
  • 基于 Schema: 即使这不是强制性的,我们仍建议使用 JSON Schema 来做路由(route)验证及输出内容的序列化,Fastify 在内部将 schema 编译为高效的函数并执行。
  • 日志: 日志是非常重要且代价高昂的。我们选择了最好的日志记录程序来尽量消除这一成本,这就是 Pino!
  • 对开发人员友好: 框架的使用很友好,帮助开发人员处理日常工作,并且不牺牲性能和安全性。
  • 支持 TypeScript : 我们努力维护一个 TypeScript 类型声明文件,以便支持不断增长的 TypeScript 社区。

快速上手

通过 NPM 安装 fastify:

npm install fastify

然后创建 server.js 文件并输入如下内容:

// Require the framework and instantiate it
const fastify = require('fastify')({ logger: true })

// Declare a route
fastify.get('/', (request, reply) => {
  reply.send({ hello: 'world' })
})

// Run the server!
fastify.listen(3000, (err) => {
  if (err) {
    fastify.log.error(err)
    process.exit(1)
  }
  fastify.log.info(`server listening on ${fastify.server.address().port}`)
})
// Require the framework and instantiate it
const fastify = require('fastify')({ logger: true })

// Declare a route
fastify.get('/', async (request, reply) => {
  return { hello: 'world' }
})

// Run the server!
const start = async () => {
  try {
    await fastify.listen(3000)
    fastify.log.info(`server listening on ${fastify.server.address().port}`)
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()

最后,通过如下命令启动:

node server

测试地址:

curl http://localhost:3000

Request/Response 验证和钩子(hook)

当然,Fastify 能做的比这些更多。

例如,你可以使用 JSON Schema 轻松地提供输入和输出验证,并在执行处理程序之前执行特定操作:

const fastify = require('fastify')({ logger: true })

fastify.route({
  method: 'GET',
  url: '/',
  schema: {
    // request needs to have a querystring with a `name` parameter
    querystring: {
      name: { type: 'string' }
    },
    // 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(3000, (err) => {
  if (err) {
    fastify.log.error(err)
    process.exit(1)
  }
  fastify.log.info(`server listening on ${fastify.server.address().port}`)
})
const fastify = require('fastify')({ logger: true })

fastify.route({
  method: 'GET',
  url: '/',
  schema: {
    // request needs to have a querystring with a `name` parameter
    querystring: {
      name: { type: 'string' }
    },
    // 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
  beforeHandler: async (request, reply) => {
    // E.g. check authentication
  },
  handler: async (request, reply) => {
    return { hello: 'world' }
  }
})

const start = async () => {
  try {
    await fastify.listen(3000)
    fastify.log.info(`server listening on ${fastify.server.address().port}`)
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()

支持 TypeScript

Fastify 附带了一个 typings 文件,因此你需要安装 @types/node,具体取决于你所使用的 Node.js 版本。

以下示例创建了一个 http 服务。

我们向所使用的 http 版本传递相关的 typings。

在路由中,通过传递类型,我们可以获取到正确类型化的底层 http 对象。

如果使用的是 http2,需要传递 <http2.Http2Server, http2.Http2ServerRequest, http2.Http2ServerResponse>

对于 https,需要传递 http2.Http2SecureServerhttp.SecureServer 而不是 Server。

这确保了在服务的处理程序中,我们还可以通过 reply.res 获取到具有正确 typings 的 http.ServerResponse

import * as fastify from 'fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'

const server: fastify.FastifyInstance = fastify({})

const opts: fastify.RouteShorthandOptions = {
  schema: {
    response: {
      200: {
        type: 'object',
        properties: {
          pong: {
            type: 'string'
          }
        }
      }
    }
  }
}

server.get('/ping', opts, (request, reply) => {
  reply.send({ pong: 'it worked!' })
})

server.listen(3000, (err) => {
  if (err) {
    server.log.error(err)
    process.exit(1)
  }
  server.log.info(`server listening on ${server.server.address().port}`)
})
import * as fastify from 'fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'

const server: fastify.FastifyInstance = fastify({})

const opts: fastify.RouteShorthandOptions = {
  schema: {
    response: {
      200: {
        type: 'object',
        properties: {
          pong: {
            type: 'string'
          }
        }
      }
    }
  }
}

server.get('/ping', opts, async (request, reply) => {
  return { pong: 'it worked!' }
})

server.listen(3000, (err) => {
  if (err) {
    server.log.error(err)
    process.exit(1)
  }
  server.log.info(`server listening on ${server.server.address().port}`)
})

请阅读 文档 并了解 Fastify 已经提供的更多功能。

一个速度快的 web 框架

基于我们在 Node.js 性能方面的经验,Fastify 从一开始就奔着 尽可能快 的目标来构建的。请查看一下我们的 基准测试章节 列出的 Fastify 与其它常见 web 框架之间的性能对比。

生态系统

Fastify 拥有一个不断增长的插件生态。你最喜欢的数据库或模板语言可能也已经有 Fastify 插件了。 请前往 生态系统 页面浏览当前可用的插件。 找不到你所需要的插件吗?小 case,自己动手写一个也很容易