1K Views
November 10, 24
スライド概要
SaCSS Season 2 Vol.14の登壇資料
Orvalによる フロントエンドの型安全性向上 2024/11/06 Kou 1
自己紹介 Kou - プログラマー - PHP、React、Azure - Sapporo Engineer Base 運営 - 初めてISUCONに参加✨ - 趣味 - NBA観戦 - SNS - @kou_tech_1017 2
はじめに 3
システムの構成 フロントエンド: - React、TypeScript バックエンド: - Laravel データフェッチ: - SWR HTTPクライアント: - Axios 4
SWR SWRはVercel社が開発したReact Hooksベースのデータフェッチライブラリである。 SPA(シングルページアプリケーション)の開発において特に有用で、クライアントサイド のデータ管理を効率化する。 社内の開発実績があったり、必要最小限でシンプルな機能を持つことから、SPAの構築 に適したSWRを採用している。 5
課題 6
当初のAPIの型付け実装例 型定義を手動で作成。 SWRのジェネリクス型を手動で指定。 7
手動でAPI型付けの課題 人為的なミスが発生しやすい APIの変更に追従するのが困難 型の一貫性を保つのが難しく、信頼性が低下 8
人為的なミスが発生しやすい 手動で定義した型とAPIレスポンスの構造が不一致となる問題が発生する。 特にフィールド名の命名規則、日付フォーマット指定による解釈の違いが顕著 である。 例: - createdAt - created_at 9
APIの変更に追従するのが困難 APIが変更されると、手動で型を更新する必要がある。 変更が頻繁に発生する場合、型定義が古くなりやすく、新しいAPI仕様に追従し づらい。 フロントエンドとバックエンド間のコミュニケーションコストが増加する。 10
型の一貫性を保つのが難しく、信頼性が低下 類似する型定義の増加 例: 11
スキーマ駆動開発 データ構造やAPIの仕様をスキーマとして定義し、そのスキーマに基づいて開 発を進める手法である。 APIに型を導入するための代表的な方法 ● OpenAPI 👈 ● GraphQLスキーマ ● gRPC/Protocol Buffers 12
解決案 OpenAPI仕様書は既に存在していた。 プロジェクトの規模はまだ大きくない。 Orvalを導入し、OpenAPI仕様書から型定義とAPIクライアントコードを自動生成 することにした。 13
OpenAPI 14
OpenAPI RESTful APIの仕様を定義するための標準的なフォーマットであり、APIの設計、ドキュメ ント化、テスト、コード生成などを支援する。 Swaggerから始まり、現在はOpenAPI Initiativeによって管理されている業界標準となって いる。 OpenAPI仕様は主にYAMLまたはJSON形式で作成される。 15
OpenAPIに基づいたAPI仕様書 16
OpenAPIの利点 Gitなどのバージョン管理ツールと相性が良く、チームでの変更履歴や差分を簡単に管 理できる。 最新の仕様が常に共有されるため、属人化せずチーム全体で理解を共有しやすい。 スキーマを基にフロントエンドとバックエンドの開発を並行して進められ、コミュニケーショ ンコストが削減される。 17
OpenAPIの不利点 学習コストがかかる。 OpenAPIのスキーマの枠組みから外れる柔軟な操作や部分的なレスポンス制御などは 難しい。 仕様書の維持管理するために、ツールやエコシステムに依存することになる。 - Apidog Stoplight 18
Orval 19
Orvalの紹介 Orvalは、OpenAPI仕様からTypeScriptの型定義とクライアントコードを自動生 成するツールである。 Orvalの開発者は、フロントエンドとバックエンドのチーム間にSwaggerを頻繁に 使用していた経験から、このツールを開発した。 動機は従来のSwaggerエディタやSwagger Codegenでは、開発者のニーズを十 分に満たせなかったこと。 https://orval.dev/overview 20
Orvalのアプローチポイント 生産性の向上 - 数秒でAPIが準備でき、時間を節約できる。 - 標準フォーマットを適用することで、人為的なエラーを防ぎ、確実なリターン結果 を保証する。 エラーバウンダリ - 標準化されたAPI仕様を得ることで、チーム間の誤解やミスを削減する。 APIモック機能 - バックエンドの準備を待つことなくアプリケーションをテストできる。 - Orvalでモックを生成し、API接続に対応できる準備が整う。 21
Orvalの主な機能と特徴 主な機能は次の通りである。 ● TypeScriptモデルの自動生成 ● クライアントコードを自動生成 ● MSW(Mock Service Worker)によるモックの生成 Orvalは、デフォルトでAxiosを使用したクライアントを生成する。 Angular、Vueなどにも対応可能である。 SWRやTanStack Queryといったデータフェッチライブラリと簡単に統合できる。 モックが自動生成されるため、開発初期段階からフロントエンド開発を進められる。 22
他のライブラリとの比較 23
他のライブラリ openapi-typescript - 型定義のみを自動生成する クライアント生成やモック生成機能は提供していない https://openapi-ts.dev/ swagger-typescript-api - 型定義とAPIクライアントコードを生成する テンプレートを基にコードを自動生成するため、SWRを使用するにはカスタムテンプ レートの作成が必要となる。 https://github.com/acacode/swagger-typescript-api 24
他のライブラリ openapi-typescript-codegen - 型定義とAPIクライアントのコードを自動生成する。 - SWRと直接統合する機能は提供していない - https://github.com/ferdikoomen/openapi-typescript-codegen/wiki 25
他のライブラリ openapi2aspida - 型定義とAPIクライアントを生成する。 - aspidaという日本発のライブラリを基盤としており、型安全なAPIクライアント を提供する。 - SWRとの統合は可能だが、追加の設定や依存関係が必要になる。 - https://github.com/aspida/openapi2aspida 26
Orvalの使い方 27
Orvalの使い方 基本的には設定ファイルを作成し、必 要に応じてカスタマイズして使用する。 例 - OpenAPI仕様ファイルの場所 生成されるコードの出力先 モックデータの生成オプション 28
設定例 clientにswrを指定する。 httpClientをfetchにする。 zodのスキーマファイルを出力する ように設定。 https://orval.dev/guides/client-with-zod 29
Orvalの実行 コマンドを実行し、設定ファイルに基づいてコード生成を行う。 orval --config ./orval.config.js 30
生成されたコード 31
zodを出力する理由 zodの出力は、そのままではフォームのバリデーション要件を満たさないことが 多い。 しかし、次のケースにおいては有効である。 ● ● 出力されたスキーマを基に必要なカスタマイズを行うことで、開発効率が向 上する 新規のバリデーション実装時に人為的ミスを削減できる 32
Orvalの選定理由 ● 型定義とAPIクライアントコードを自動生成ができる ● SWRと簡単に統合できる ● 生成されるコードがカスタムフックに近い構造を持つ ● モックデータを自動生成する機能を備える ● コード生成に必要なライブラリの依存関係が少ない ● 他のライブラリと比較してドキュメントが充実している(Zennに日本語訳あ り) 33
おわりに 34
ポイントと注意事項 OpenAPI仕様書を正確かつ最新の状態に保つことが重要である。 万能ではないため、生成されたクライアントコードをそのまま使用できないケースがある ことを想定しておく。 例:useSWRMutationをGETリクエストで使用できない Next.jsなどのフレームワークやSPA以外のアプリケーションでは、より適したソリューショ ンが存在する可能性がある。 ライブラリの陳腐化の可能性も考慮し、生成されたコードの理解は不可欠である。 35
まとめ OpenAPI仕様とOrvalの活用により、型安全なフロントエンド開発が実現可能である。 手動型付けの課題を解決し、開発効率と信頼性が向上する。 スキーマ駆動開発の採用で、フロントエンドとバックエンドの一貫性が保たれる。 TanStack QueryやSWRといったライブラリを使用し、スキーマ駆動開発を実践する場 合、Orvalは最適なツールであると考える。 36
参考資料 https://zenn.dev/hrbrain/articles/3ca5d37dd0b80e https://speakerdeck.com/sansantech/sansan-20230912-1 https://orval.dev/overview https://zenn.dev/fizumi/scraps/779a274262948f 37