最近一直在用 Next.js 开发我的新网站。这次写了一些 API,我就想着能不能像平时开发后端那样,使用 swagger 进行调试,所以进行了一番调研。严格来说 Next.js 本身并不直接支持 swagger,因为 swagger(更准确地说是 OpenAPI 规范)是后端 API 文档的工具,而 Next.js 是一个前端/全栈框架。不过,如果用 Next.js 的 API Routes(即 app/api/* 目录下的接口),完全可以结合 swagger 来做 API 文档。
常见做法有两种:
1.使用工具自动生成 swagger2.手动写 OpenAPI 文件
bun i next-swagger-doc使用
import { createSwaggerSpec } from 'next-swagger-doc'; import 'server-only'; export const getApiDocs = async () => { const spec = createSwaggerSpec({ apiFolder: 'app/api', definition: { openapi: '3.0.0', info: { title: 'Next Swagger API Example', version: '1.0', }, components: { securitySchemes: { BearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT', }, OAuth2: { type: 'oauth2', flows: { authorizationCode: { authorizationUrl: 'https://example.com/oauth/authorize', tokenUrl: 'https://example.com/oauth/token', scopes: { read: 'Grants read access', write: 'Grants write access', }, }, }, }, }, }, security: [], }, }); return spec; };2.创建 Swagger UI Component
bun i swagger-ui-react我这里先跟着配置一下,等会再试试 Node.js 生态的其他工具,比如 stoplightio/elements[5]
'use client'; import SwaggerUI from 'swagger-ui-react'; import 'swagger-ui-react/swagger-ui.css'; type Props = { spec: Record<string, any>; }; function ReactSwagger({ spec }: Props) { // @ts-ignore - SwaggerUI is not typed return <SwaggerUI spec={spec} />; } export default ReactSwagger;创建 API 文档页面
import { getApiDocs } from '@/lib/swagger'; import ReactSwagger from './react-swagger'; export default async function IndexPage() { const spec = await getApiDocs(); return ( <section className="container"> <ReactSwagger spec={spec} /> </section> ); }添加接口文档注释
/** * @swagger * /api/hello: * get: * description: Returns the hello world * responses: * 200: * description: Hello World! */ export async function GET(_request: Request) { // Do whatever you want return new Response('Hello World!', { status: 200, }); }查看效果
import dynamic from 'next/dynamic'; // 堆代码 duidaima.com const SwaggerUI = dynamic(() => import('swagger-ui-react'), { ssr: false }); import 'swagger-ui-react/swagger-ui.css'; export default function ApiDocs() { return <SwaggerUI url="/swagger.json" />; }可以参考: Swagger integration in next JS[6]
这俩方法看起来都不是很完美,果然 Next.js 还是偏前端吧,写太多 API 也不合适,我最近又发现一个新玩意 hono[7] ,这个框架对 edge 的支持非常好,可以考虑拿这个搭配 Next.js 来做一些小玩意,不得不说前端的技术栈更新太快了哈哈哈!
参考资料
[1] tsoa: https://github.com/lukeautry/tsoa
[2] zod-to-openapi: https://www.npmjs.com/package/zod-to-openapi
[3] next-swagger-doc: https://www.npmjs.com/package/next-swagger-doc
[4] swagger-ui-react: https://www.npmjs.com/package/swagger-ui-react
[5] stoplightio/elements: https://github.com/stoplightio/elements
[6] Swagger integration in next JS: https://www.reddit.com/r/nextjs/comments/1lm1hm6/swagger_integration_in_next_js/
[7] hono: https://hono.dev/