Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
DartによるBFF構築・運用 〜 Dart Frog × Melos 〜
Search
Ryotaro Onoue
November 10, 2023
Programming
2
2.7k
DartによるBFF構築・運用 〜 Dart Frog × Melos 〜
FlutterKaigi 2023 登壇資料
Ryotaro Onoue
November 10, 2023
Tweet
Share
More Decks by Ryotaro Onoue
See All by Ryotaro Onoue
Apple Walletでパスを作るお話
yumnumm
0
130
私がやってきたアウトプット集
yumnumm
0
110
俺/私のこだわりデスク大大大自慢LT大会 (LTFes #12)
yumnumm
0
56
仕事以外で作成したプロダクトの自慢大会
yumnumm
0
59
Cloudflare Workers でプリントシール機の画像共有システムを制作したお話 @serverlessF
yumnumm
0
210
Flutter × Jetpack Composeの相互運用 @ GDG Tokyo 2023
yumnumm
0
1k
Flutterでもシリアルコンソール通信 できるもん!
yumnumm
0
790
Flutterハンズオン
yumnumm
0
110
Flutterでも地図を描きたいお話
yumnumm
1
500
Other Decks in Programming
See All in Programming
どうして僕の作ったクラスが手続き型と言われなきゃいけないんですか
akikogoto
1
120
タクシーアプリ『GO』のリアルタイムデータ分析基盤における機械学習サービスの活用
mot_techtalk
4
1.4k
Arm移行タイムアタック
qnighy
0
320
WebフロントエンドにおけるGraphQL(あるいはバックエンドのAPI)との向き合い方 / #241106_plk_frontend
izumin5210
4
1.4k
Snowflake x dbtで作るセキュアでアジャイルなデータ基盤
tsoshiro
2
520
What’s New in Compose Multiplatform - A Live Tour (droidcon London 2024)
zsmb
1
470
Click-free releases & the making of a CLI app
oheyadam
2
110
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
100
AWS IaCの注目アップデート 2024年10月版
konokenj
3
3.3k
Jakarta EE meets AI
ivargrimstad
0
610
レガシーシステムにどう立ち向かうか 複雑さと理想と現実/vs-legacy
suzukihoge
14
2.2k
イベント駆動で成長して委員会
happymana
1
320
Featured
See All Featured
Designing the Hi-DPI Web
ddemaree
280
34k
Facilitating Awesome Meetings
lara
50
6.1k
What's in a price? How to price your products and services
michaelherold
243
12k
VelocityConf: Rendering Performance Case Studies
addyosmani
325
24k
GraphQLとの向き合い方2022年版
quramy
43
13k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
109
49k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
1.9k
The Language of Interfaces
destraynor
154
24k
The Pragmatic Product Professional
lauravandoore
31
6.3k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
A Modern Web Designer's Workflow
chriscoyier
693
190k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
Transcript
スピーカー名 DartによるBFF構築・運用 〜 Dart Frog × Melos 〜 もぐもぐ /
K9i
自己紹介
もぐもぐ ↓こんなの
もぐもぐ - Ryotaro Onoue - なんでもぐもぐにしたのか覚えてません - 食べるのは好きです - ゆめみのFlutterエンジニア
- 2023年4月に新卒として入社 - Flutter/Dart歴 3年
もぐもぐ - 地震関連のアプリ開発してます - 今年中にアプリストアでリ リース予定
K9i
K9i - Kota Hayashi - K9iはK8s(Kubernetes)とかL10n(Localization)と同じ感じ - Kota->Tako->🐙 - K9iはケーナインアイだがいいづらいので、林呼び推奨
- ゆめみのFlutterリードエンジニア - 1社目:Androidなど(この時期に趣味でFlutterをはじめた) - 2社目:Flutter - 3社目:今年の5月からゆめみ - Flutterは4年目くらい
K9i - RiverpodのChangelogに稀に生息
会社の紹介
株式会社ゆめみ - 公式アカウントの大喜利で有名😅
ゆめみFlutterギルド - イベントやっとります
アジェンダ
アジェンダ(1/3) 1. Dartバックエンドの世界 a. Dartのおさらい b. Dartバックエンドフレームワークの紹介 c. BFFとは 2.
プロジェクトの背景 a. ゆめみ参入の経緯 b. バックエンドの構成変更 c. Flutter向けBFFの方針 前半
アジェンダ(2/3) 3. 技術スタックの紹介 a. Flutterチーム担当領域のプロジェクト構成 b. Dart Frog解説 c. Melos解説
4. 実践した感想 a. Dockerのつらみ b. [TODO] 後半
アジェンダ(3/3) 5. Liveデモ a. [TODO] 6. まとめ 後半
1. Dartバックエンドの世界
Dartのおさらい
Dartとは - Googleが開発 - 2011年10月10日に登場
Dartのこれまで(超ダイジェスト) - JavaScriptの代替となることを目的に作られた - 2011年末までにVMがChromeに統合される予定だった - 普及は進まず2015年にはChrome統合を断念 - Skyフレームワーク(Flutterの前身)がJavaScriptの変わりとなる言語と 探していたところDartと出会う
- 2015年にSkyがDartをはじめて導入 - 以降Flutterとともに成長し今に至る
Dartバックエンドという選択肢 - Flutterの普及に伴いバックエンドもDartで開発したい欲求 - 言語を統一することで様々なメリット - 同じメンバーがフロントエンドもバックエンドも開発 - コードの共有・再利用 -
ツール・ライブラリの共通化 - etc…
Dartバックエンド フレームワークの紹介
Aquaduct - 概要 - 懐かしかったので紹介(知ってたら古参?) - Stable Kernelが2018年に開発 - 2021年に開発中止されリポジトリはPublic
archive - Conduct - AquaductのFork - 活発に開発されてはなさそう?(最終更新半年前)
Serverpod - Serverpod社が開発するFlutter向けのアプリサーバー - トップページに「The missing server for Flutter」とありFlutterを 強く意識している
- 2021年に発表され、2023年1月31日に1.0になった - CLIでプロジェクトを作成するとFlutterアプリとバックエンドが両方作成さ れる - 後述するDart Frogなどに比べ多機能な印象
Shelf - Dartチームによって開発されているサーバーフレームワーク - 0.1.0は2014年に公開 - Shelf本体は軽量 - 複数のShelf用パッケージを組み合わせて使うモジュール方式 -
shelfのリポジトリだけでも複数のパッケージが存在
None
Dart Frog - VGV(Very Good Ventures)が開発しているサーバーフレームワーク - 開発元がFlutter界隈で有名なので注目されている - 2022年に発表され、2023年8月2日に1.0.0になった
- Shelfをベースに構築されている、Shelf同様軽量 - こちらも複数パッケージを組み合わせるモジュール方式 - Shelfをより便利に使えるような機能がある - 技術スタック紹介の章で説明
BFFとは
BFFとは - BFF(Backend For Frontend) - 初めて名前を聞くと言う人もいるかも? - フロントエンド(アプリ含む)とバックエンドの中間に置かれるサーバー -
???
BFFの例1:バックエンドが複数
BFFの例2:フロントエンドが複数
BFFとは - メリット - APIの集約 - 複数のバックエンドを一つのAPIでフロントエンドに提供 - 特定のフロントエンドに特化 -
WebにはGraphQL、アプリにはREST - 開発言語も対応するフロントエンドと揃えたりできる - デメリット - 開発コスト - 複雑・冗長
2. プロジェクトの背景
ゆめみの参入の経緯
参入プロジェクト - 介護・看護分野の企業と労働者のマッチングサービス - PMF(プロダクトマーケットフィット)の段階 - フロントエンドは3種類存在 - 企業用Webフロントエンド -
労働者用Webフロントエンド - 労働者用モバイルアプリ(これを担当)
参入前のプロジェクトのメンバー - バックエンド、PMなど:顧客企業の方がフルタイム稼働 - ゆめみはクライアントワーク - Webフロント:ゆめみのフロントメンバー(別チーム)が日中稼働 - モバイルアプリ:副業メンバーが夜間など不規則な稼働
参入前の課題 - モバイルアプリの開発メンバーが不規則な稼働 - クライアント企業の方とコミュニケーションがとりづらい - 思うようにモバイルアプリ開発が進んでいなかった - Flutter・Dart得意なメンバー不在 -
全体的に負債の塊 - ゆめみのFlutterギルド参入で課題を解決したい - 今年8月〜
バックエンドの構成変更
バックエンドの構成変更 - プロジェクト参入次点でバックエンドの構成変更が進行中 - PMF期に生じた負債の解消
元々の構成
元々の構成 旧バックエンドは元々モバイルアプリ 用に作られたが、Webからも使われ るようになってしまう 特定のフロントエンドのための分岐と うで複雑に
目的とする構成
目的とする構成 フロントエンドごとに BFFを作り、特定 のフロントエンドのためのロジックを 移譲 旧バックエンドは廃止
Flutter向けBFFの方針
Flutterチームの担当
Flutter向けBFFの方針 - 実は作り途中のBFFがあったが… - 色々と課題… - 廃止されるまでは旧バックエンドも部分的に使う - Dartで統一 -
Jsonをやり取りするクラスをクライアントと共通化 - せっかく新規に作るので気になる技術を試す - Dart Frog、Melos - 賛否有りそうだけど大事
Flutter向けBFFの方針
Flutter向けBFFの方針 旧バックエンドを当分は直接利用 いずれは消える
Flutter向けBFFの方針 初期リリースでは一部のエンドポイン トラップ(とりあえず動かすため)
3. 技術スタックの紹介
Flutterチーム担当領域の プロジェクト構成
リポジトリ・パッケージ構成
主な利用技術 - Melos - マルチパッケージ構成の管理に利用 - Dart Frog - BFFの実装に利用
- Freezed、JsonSerializable - クライアントとBFFで共有する通信用の型で利用 - 一般的だと思うので解説しません🙏
Melos解説
マルチパッケージとは - 複数のDartパッケージでプロジェクトを構成する手法 - 機能やレイヤーごとのディレクトリを作るのではなく、パッケージに切 り出す - パッケージごとにリポジトリを作ると管理が大変なため、1つのリポジトリで 複数パッケージを管理するのが一般的 -
モノレポともいう
マルチパッケージ利点 - 大規模なアプリで機能・レイヤーごとにパッケージを分ける - 関心の分離 - 意図しない依存を防ぎやすい - 共有コードをパッケージに切り出せる -
今回やりたかったこと
Melosとは - Dartでのマルチパッケージを支援するコマンドラインツール - Invertaseが開発しており、有名パッケージの開発にも使われている - Riverpod、FlutterFireなどが利用 - Melosの開発にもMelosが使われている -
注意:マルチパッケージならMelos必須というわけではない - 使ってないリポジトリも - Flutter News Toolkit、I/O Flip
Melosのはじめかた - グローバルにインストール - dart pub global activate melos -
プロジェクトのルートにmelos.yamlを作る - melosのコマンドが使えるようになる
Melosの機能 - Commands - Filter - Scripts
Commands - モノレポをやりやすくするいくつかのコマンドがある - bootstrap / clean - exec -
list - publish - run - version
Commands - モノレポをやりやすくするいくつかのコマンドがある - bootstrap / clean - exec -
list - publish - run - version これらを紹介
bootstrap / clean - 複数パッケージに対してpub get - pubspec_overrides.yamlの用意 - リポジトリ内の依存を相対パスでoverrideして開発中バージョンを使
うようにする - 問題に気づきやすくなるなど利点がある - cleanはbootstrapの逆
exec - モノレポ内の複数のパッケージに対して同じコマンドを実行 - これがないと一々ディレクトリ移動してbuild_runner実行みたいにな る - 後述するfilter機能と組み合わせる
list - モノレポ内のパッケージをリスト表示 - 依存関係などを簡単に確認
publsh - モノレポ内のパッケージをpub.devに公開しやすくするコマンド - アプリ作る分には使わない
run - 後述するScripts機能を実行するコマンド
version - Conventional Commitsの作法に従っている場合に自動でバージョニン グができる - 「feat: hoge」みたいなcommit - !をつけると破壊的変更としてメジャーバージョンがあがるなどのルー
ルがある(feat!: hoge) - tagで前回からの差分を判断 - 手動バージョニングにも使える
Filter - Commandsの対象パッケージを絞り込む機能 - melos bootstrap --no-privateなら--no-private部分 - いくつかのフィルターがある -
scope:特定の文字列を含むパッケージのみ - depends-on:特定のパッケージに依存してるパッケージのみ - 他にも色々
Scripts - melos.yamlにスクリプトを定義しておきrunコマンドで実行できる - よく使うものを登録しておき、CIからも使うと良い感じ
Dart Frog解説
Dart Frog(再掲) - VGV(Very Good Ventures)が開発しているサーバーフレームワーク - 開発元がFlutter界隈で有名なので注目されている - 2022年に発表され、2023年8月2日に1.0.0になった
- Shelf上に構築されており、Shelf同様軽量 - こちらも複数パッケージを組み合わせるモジュール方式 - Shelfをより便利に使えるような機能がある - 技術スタック紹介の章で説明
Dart Frogのはじめかた - グローバルにインストール - dart pub global activate dart_frog_cli
- DartのコマンドラインツールなのでMelosと同じ - dart_frog create my_project - 最低限のDart Drogのコード - dart_frog devですぐ動く
Dart Frogの基本機能・特徴 - ホットリロード対応 - ファイルベースルーティング - 便利なクラス - Middleware
- DI - テストの容易性
ファイルベースルーティング - ディレクトリ構成がそのままルーティングに対応する - ”/”と”/hello”のエンドポイントに対応させる場合 - 画像のどちらか - 競合したらビルド失敗等で分かる
エンドポイントの追加方法 - もちろん手動でファイルを追加すればできるが - コマンドで追加も可能 - dart_frog new route "/hello"
追加直後のエンドポイント - RequestContextを受け取ってResponseを返す関数
エンドポイントの追加方法 - もちろん手動でファイルを追加すればできるが - コマンドで追加も可能 - dart_frog new route "/hello"
- dart_frog_cliのコマンドはMasonで実現されている - Masonはテンプレートからコードを生成するDartツール - ファイルベースルーティングなのはテンプレートからの生成との 相性が良いからかも?
None
便利なクラス - Dart FrogはShelfのクラスをラップして便利にしている - 先程のRequestContext
RequestContext
RequestContext - 内部的にshelfのRequest
body、jsonなどよく使うであろうメソッ ドが事前に用意されている
Middleware - ディレクトリごとに配置でき、サブディレクトリ含めて前処理を行える
Middleware - handlerのuseにMiddleware(requestLogger)を渡す - 用途 - ロガー - 共通のエラー処理 -
DI
Middlewareのチェイン - useはMiddlewareを受 け取りHandlerを返すの でチェインできる
補足:Shelfのリソースを活用
DI - providerというMiddlewareでDIできる
DI - middlewareでこうして
DI - 利用側はRequestContextから取得
テストの容易性 - プロジェクト初期化次点でmock_tailが追加されている
テストの容易性
テストの容易性 RequestContextはmocktailでモッ ク
テストの容易性 onRequest関数をテストすれば良い
テストの容易性 expectで確認!で完了
もぐもぐタイム
4. 実践した感想
サンプルコード - 実際のソースコードを見せることはできないので、簡素化したサンプルプ ロジェクトを作成しました - GitHub Repository Search APIの検索結果をBFFでキャッシュします -
https://github.com/YumNumm/dart-frog-github-repository-se arch - 後でライブデモをするので そこで詳しくお話します
サンプルコード
1. バックエンド と BFF のクライアントを同じように実 装できた - アプリがBFFを叩く部分 と BFFがバックエンドAPIを叩く部分で同じパッ
ケージを使った - 実装が似ているのでキャッチアップしやすい - retrofitを利用してクライアントを実装しました
2. API型定義の取り方 - 実際の案件では、 Flutter App と BFF のリポジトリが別 -
Flutter Appは BFFのリポジトリにある 型定義へ依存している - どうするねん!
2. API型定義の取り方
2. API型定義の取り方 - bff_api_typesをpub.devで公開すれば良いんじゃ!? → インシデント確定演出 - git submoduleで置いて、path packageとして扱う
→ 微妙 - pubspec.yamlのgit packageとして扱う → git経由の依存関係 よござんす👍
API型定義の取り方 - bff_api_typesをpub.devで公開すれば良いんじゃ!? → インシデント確定演出 - git submoduleで置いて、path packageとして扱う →
チョット汚い - pubspec.yamlのgit packageとして扱う → よござんす👍 CI環境どうする!? - actions/checkoutでAppのコードをクローンしている - BFFのレポジトリはクローンできない
2. API型定義の取り方 - GitHub Deploy Keyのすゝめ - Deploy Keyとは? -
単一リポジトリへのアクセス(R, R/W)を許可するSSHキー - サーバ上でプロジェクトを起動するためのもの - publicな部分をリポジトリに privateな部分をサーバに配置 - ユーザに紐づかないため、管理が楽 cf. https://docs.github.com/ja/authentication/connecting-to-github-with-ssh/managing-deploy-keys
2. API型定義の取り方 - GitHub Deploy Keyのすゝめ - GitHub Actions内で SSHのprivate
keyを展開 - SSHできる用意をしてあげる - flutter pub get ヨシ👍
3. Docker を使う - Docker とは? - 仮想マシン(VM)とは違い、コンテナという単位でアプリケーションを実 行できる -
Dockerfileを書くことでコンテナビルド方法をコードで記述できる (IaC: Infrastracture as Code) - クラウドでもローカルでも実行できる - 実行環境依存のものを減らすことができる https://aws.amazon.com/jp/docker/ より
3. Docker を使う - プロジェクトでAWS Fargate上でデプロイする必要があった - 環境に依存せずにローカルでデバッグできるようにしたかった
OrbStackのススメ (余談) - Docker DesktopとWSLの代替品 - macOSでDocker ContainerとLinux マシンを動かすことができるApp -
Docker Desktopを使うよりも高速・軽量・シンプル https://orbstack.dev/ - 個人利用であれば無料、 商用利用は$8/month per user - macOS専用
3. Dart FrogのDockerfile 生成 - dart_frog build で build/Dockerfileが生成される -
buildコマンドを実行するためには dart_frog が実行できることが前 提 (ホスト環境に依存してはいけない) - build/* をリポジトリに含めると、差分がすごいことになるので含めた くない → 自分でDockerfile書きますわ
バイナリをビルドするための Dartコンテナ バイナリを実行するためのコンテナ builder scratch
バイナリをビルドするための Dartコンテナ バイナリを実行するためのコンテナ builder scratch ローカルで依存しているライブラリの pubspec.yamlと pubspec_overrides.yaml をコピー ローカルで依存しているライブラリの全体をコピー
バイナリを実行するためのコンテナ バイナリをビルドするための Dartコンテナ builder scratch builderで生成されたバイナリをコピーして 実行する
5. LIVEデモ
LIVEデモ - 実際のソースコードを見せることはできないので、簡素化したサンプルプ ロジェクトを作成しました - GitHub Repository Search APIの検索結果をBFFでキャッシュします -
GitHub Personal Access Tokenセット済み -> レートリミット緩和 - 仕様 - GET /api/v1/repository/search : リポジトリ検索 - param: query={検索文字列} - https://github.api.yumnumm.dev にデプロイ済み
LIVEデモ
LIVEデモ GitHub Repository Search API BFF, App
LIVEデモ - dart_frog create - dart_frog create hoge でプロジェクトを作成できる -
dart_frog dev で実行 - localhost:8080でアクセスできます - localhost:8181でDevToolへアクセスできます demo/1 Branch
LIVEデモ - melos bootstrap - melos bootstrap で pubspec_overrides.yamlが生成される -
melos clean でpubspec_overrides.yamlが消える - melos.yamlで記述したbuild_runnerスクリプトを実行できる demo/2 Branch - melos bootstrap で pubspec_overrides.yamlが生成される - melos clean でpubspec_overrides.yamlが消える - melos.yamlで記述したbuild_runnerスクリプトを実行できる
LIVEデモ - Dart Frog BFF - dart_frog new route hoge
でエンドポイントを作成できる - dart_frog dev で開発サーバを起動 - http://localhost:8080/ でアクセスできる - http://localhost:8181/ でDevToolへアクセスできる - api/v1/repository/search の中身を実装していく demo/2 Branch
LIVEデモ - Dart Frog × Docker - docker compose up
-d /-build でコンテナを起動 - [OrbStackを利用している場合] http://orb.local でコン テナ一覧を見ることができる - main Branch
LIVEデモ - Application - 実際にFlutterアプリからアクセスしてみましょう - App: https://gh-repo-search.yumnumm.dev/ - BFF:
https://github.api.yumnumm.dev/ (どちらも 2023/11/11 には閉鎖します ) main Branch
6. まとめ
1章まとめ:Dartバックエンドの世界 - Dart 12年の歴史 - Chrome統合が失敗しオワコン化? - Sky(現Flutter)に採用され復活 - Flutterの盛り上がりによりDartバックエンドの機運が高まる
- ServerPod、Dart Frogなどが盛り上がる
2章まとめ:プロジェクトの背景 - Flutterチームが夜間稼働でコミュニケーションなどに課題 - ゆめみ参戦 - PMF期に複雑化したバックエンドの構成変更 - 3つのフロントエンドそれぞれのBFF越しに共通バックエンドを叩く構 成にする
- Dart Frog x MelosのBFFつくるぞい
3章まとめ:技術スタックの紹介 - マルチパッケージ管理ツールMelosを使ってアプリとBFFでパッケージ共 有 - Melos解説 - 複数パッケージに対してコマンド実行などが便利 - Dart
Frog解説 - ファイルベースルーティングとMasonによるコード生成 - Shelfのクラスをラップした便利クラス - テストもやりやすい
4章まとめ:実践した感想 - バックエンドとBFFのClient実装がほぼ同じ - BFF API 型定義をApp側と共有することで 保守性向上 - モノレポでローカル依存が多いならではの
Dockerfileのつらみ
5章まとめ:ライブデモ - 実際のプロダクトにBFFを取り込む過程を紹介 - melos, dart_frog を利用することで、高速に開発を進めることができて いる - Dockerを利用してローカルで開発を行うこともできます
告知 - この後同じルームでゆめみスポンサーセッション🥳 通称:モリモリ山トリオ
Links - https://ja.wikipedia.org/wiki/Dart - https://zenn.dev/mjhd/articles/680a19ae893c1e - https://github.com/stablekernel/aqueduct - https://serverpod.dev/ -
https://pub.dev/packages/shelf - https://dartfrog.vgv.dev/ - https://github.com/felangel/mason - https://blog.codemagic.io/writing-your-backend-in-dart / -
Links - https://zenn.dev/overflow_offers/articles/20220418-wha t-is-bff-architecture - https://melos.invertase.dev/ - https://www.conventionalcommits.org/ja/v1.0.0/ - スライド内のサンプルプログラム
- GitHub API BFF+App: https://github.com/YumNumm/dart-frog-github-reposi tory-search
None