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.9k
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
140
私がやってきたアウトプット集
yumnumm
0
120
俺/私のこだわりデスク大大大自慢LT大会 (LTFes #12)
yumnumm
0
58
仕事以外で作成したプロダクトの自慢大会
yumnumm
0
64
Cloudflare Workers でプリントシール機の画像共有システムを制作したお話 @serverlessF
yumnumm
0
220
Flutter × Jetpack Composeの相互運用 @ GDG Tokyo 2023
yumnumm
0
1k
Flutterでもシリアルコンソール通信 できるもん!
yumnumm
0
820
Flutterハンズオン
yumnumm
0
110
Flutterでも地図を描きたいお話
yumnumm
1
520
Other Decks in Programming
See All in Programming
Webエンジニア主体のモバイルチームの 生産性を高く保つためにやったこと
igreenwood
0
330
DevFest Tokyo 2025 - Flutter のアプリアーキテクチャ現在地点
wasabeef
5
900
Keeping it Ruby: Why Your Product Needs a Ruby SDK - RubyWorld 2024
envek
0
180
MCP with Cloudflare Workers
yusukebe
2
220
HTTP compression in PHP and Symfony apps
dunglas
2
1.7k
PHPで学ぶプログラミングの教訓 / Lessons in Programming Learned through PHP
nrslib
2
170
KubeCon + CloudNativeCon NA 2024 Overviewat Kubernetes Meetup Tokyo #68 / amsy810_k8sjp68
masayaaoyama
0
250
今年一番支援させていただいたのは認証系サービスでした
satoshi256kbyte
1
250
たのしいparse.y
ydah
3
120
PHPで作るWebSocketサーバー ~リアクティブなアプリケーションを知るために~ / WebSocket Server in PHP - To know reactive applications
seike460
PRO
2
170
テストコード文化を0から作り、変化し続けた組織
kazatohiei
2
1.5k
良いユニットテストを書こう
mototakatsu
5
2k
Featured
See All Featured
Scaling GitHub
holman
458
140k
Adopting Sorbet at Scale
ufuk
73
9.1k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Testing 201, or: Great Expectations
jmmastey
40
7.1k
Unsuck your backbone
ammeep
669
57k
Put a Button on it: Removing Barriers to Going Fast.
kastner
59
3.6k
Code Reviewing Like a Champion
maltzj
520
39k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.7k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
6
510
Building Applications with DynamoDB
mza
91
6.1k
KATA
mclloyd
29
14k
Side Projects
sachag
452
42k
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