🍄

SwaggerをReactアプリ内に掲載したい

2024/12/01に公開

やりたいこと

React で GUI アプリケーションを作成していますが、API もユーザーに公開しています。
ユーザーへ公開するためのドキュメントは別管理していましたが、アプリと合わせて更新できた方が更新忘れもなくリリース対象も減るので、API リファレンスもアプリケーション内に掲載するようにします。
手間を減らすため、実装時にバックエンドと共有している OpenAPI 形式の yaml ファイルをそのまま使いたいです。

動作確認環境

パッケージ バージョン
node 22.11.0
yarn 1.22.17
React 18.3.1
vite 6.0.1
Typescript 5.6.2

手順

React をセットアップ

React + Vite +Typescript でプロジェクトを作成します。

プラグインをインストール

Swagger 表示プラグインである swagger-ui-react をインストールします。

https://www.npmjs.com/package/swagger-ui-react

$ yarn add swagger-ui-react
info Direct dependencies
└─ swagger-ui-react@5.18.2

Typescript 用に型定義もインストールします。

$ yarn add -D @types/swagger-ui-react
info Direct dependencies
└─ @types/swagger-ui-react@4.18.3

本筋ではないですが、ルーティング用に react-router-dom もインストールします。

$ yarn add react-router-dom
info Direct dependencies
└─ react-router-dom@7.0.1

実装

API 定義は OpenAPI 形式の yaml ファイルで管理されています。
このファイルを読み込んでアプリケーション内の1ページに表示します。

できあがった全体を示します。

ファイル構成

├── eslint.config.js
├── index.html
├── package.json
├── public
│   └── api
│       └── reference.yaml // 追加
├── src
│   ├── index.css
│   ├── main.tsx // 編集
│   ├── pages
│   │   └── ApiReference
│   │       └── index.tsx  // 追加
│   └── vite-env.d.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── yarn.lock

public/api/reference.yaml

ここでは Swagger のサンプルコードをコピーしてきただけです。プロジェクトのファイルに差し替えてください。

public/api/reference.yaml
openapi: 3.0.0
info:
  title: Sample API
  description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
  version: 0.1.9

servers:
  - url: http://api.example.com/v1
    description: Optional server description, e.g. Main (production) server
  - url: http://staging-api.example.com
    description: Optional server description, e.g. Internal staging server for testing

paths:
  /users:
    get:
      summary: Returns a list of users.
      description: Optional extended description in CommonMark or HTML.
      responses:
        "200": # status code
          description: A JSON array of user names
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string

src/main.tsx

今回作ったページへのルーティングを追加。

main.tsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
+ import { BrowserRouter, Route, Routes } from "react-router-dom";
+ import ApiReference from "./pages/ApiReference/index.tsx";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
+    <BrowserRouter>
+      <Routes>
+        <Route path="/api-reference" element={<ApiReference />} />
+      </Routes>
+    </BrowserRouter>
  </StrictMode>
);

src/pages/ApiReference/index.tsx

src/pages/ApiReference/index.tsx
import React from "react";
import SwaggerUI from "swagger-ui-react";

import "swagger-ui-react/swagger-ui.css";

const ApiReference: React.FC = () => {
  return (
    <div style={{
        backgroundColor: "#fff"
    }}>
      <SwaggerUI url={"/api/reference.yaml"} />
      </div>
  );
};

export default ApiReference;

これのみだとダークモードに対応していなかったので背景白だけ入れました。
実プロジェクトではベーススタイルが設定されていると思うので、その中でレイアウトは調整してください。
MUI を使っているアプリケーション内では、特にスタイル衝突せずきれいに表示されました。

できないこと

Swagger では複数のファイルを指定したらファイル切り替えできる UI がヘッダーに表示されるのですが、このプラグインでは1ファイルしか指定することができません。
もし複数ファイルを扱いたい場合は、ファイル切り替えは自前で用意する必要があります。

まとめ

プラグインを使っただけで簡単に表示できました。

Discussion