Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
React Native + Cloudflare Worker で個人開発アプリを作っている話
Search
Kyosuke Hiraizumi
August 07, 2024
850
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React Native + Cloudflare Worker で個人開発アプリを作っている話
React Native Meetup #17 の登壇資料です。
Kyosuke Hiraizumi
August 07, 2024
Featured
See All Featured
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
540
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
500
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
520
The Pragmatic Product Professional
lauravandoore
37
7.4k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
520
AI: The stuff that nobody shows you
jnunemaker
PRO
9
990
Tell your own story through comics
letsgokoyo
1
1.1k
Optimising Largest Contentful Paint
csswizardry
37
4k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
How to Ace a Technical Interview
jacobian
281
24k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
250
Transcript
React Native + Cloudflare Worker で 個人開発アプリを作っている話 2024/08/06 React Native
Meetup #17
自己紹介 平泉 京祐 / @hirai_kyo / github.com:HiraiKyo 所属: CA技研 技術:
仕事で ROS / Python / C++ 趣味・副業で Typescript / Node.js / C# 趣味: ポーカーやってます!
アプリ名: Hashigo コンセプト • テニスの対戦アプリ • ワンボタンで適切な対戦相手 が見つかる
LT趣旨 • 完成まで来たので、とりあえず自慢したかった!! • 技術的な深堀りポイントは特にない… ◦ 企画 ~ 設計 ~
実装 の俯瞰的LTができれば • ビジネスモデルから詳細設計まで質問対応するLTは珍しい(?) • (おまけ) バックエンドにCloudflare Workerを採用した話
アプリ企画
Hashigoで解決する課題 既存テニスアプリの調査 顕在ニーズ 実力が自己申告制 Lv1 ~ 10 を自分で設定 同レベルでも結構差がある ⇒
ELOレーティング導入 潜在ニーズ 相手を探すのが手間 場所, 日時, 参加者, レベル, etc… Tinderくらい手軽に探したい ⇒ マッチメイキング方式を採用 ELOベースのマッチメイキング方式テニス対戦アプリ
Hashigo システム概要 クライアント マッチメイキングへ参加 マッチ成立の通知受け取り マッチ成立後のコミュニケーション サーバ マッチメイキングの定期実行 マッチメイクアルゴリズム マッチ成立のプッシュ通知
アプリ設計
Hashigoの技術スタック・構成 フロント Expo (React Native) Typescript バック Cloudflare Worker Typescript
フロント技術選定 ビジネス要件 • マッチ成立通知 • 位置情報 • サービス開始時にユーザーがある程度必要 技術要件 •
Dartつらいかも、TS, React はたくさん触ってる
アプリ実装
Hashigo クライアント側の機能 機能要件 位置情報 expo-location 地図表示 react-native-maps ユーザプロフィールの編集 react-hook-form プロフィール画像のアップロード
expo-image-picker プッシュ通知 expo-notifications WebSocketでマッチメイキングサーバと通信 標準ライブラリ 非機能要件 認証 Firebase JS SDK UIライブラリ React Native Paper エラーログ収集 Sentry
Expo SDK が提供するライブラリを 使っただけ。
None
Thank you.
None
Q. 営業どうしてるの? A. 私がテニスしに行って宣伝してます。 暑すぎて熱中症2回なりました…。
Q. Cloudflare Worker 良い? A. とても良い。 ホットスタートなのに安い(コンテナベースではないので) DurableObjectsが直観的で使いやすい WebSocket Hibernation
APIでWebSocketのコストダウン狙える Cloudflare といえば WAF がある!
マッチメイキングサーバ OpenMatch • ゲーム向けのOSSマッチメイクフ レームワーク • マッチメイクロジックをどこまで弄れ るか分からなかった • ドキュメントが整っていない
自作 • コアであるマッチメイクロジックを 外部に依存したくなかった • Cloudflare DurableObjectsが 使いやすい! • クラウド上に存在するシングルトン クラス • WebSocket Hibernationでコス トダウンも可能
サーバサイド : Cloudflare DurableObjects の実装例 export class MatchmakingDurableObject extends DurableObject
{ private _queues: QueueType[] = []; constructor(readonly state: DurableObjectState, readonly env: Env) { super(state, env); this.state.blockConcurrencyWhile(async () => { let stored = await this.state.storage.get<string>('queue'); this._queues = stored ? JSON.parse(stored) : []; }); } async addQueue(participant: Participant): Promise<void> { const q: QueueType = { queueId: uuidv4(), participant, createdAt: new Date(), }; this._queues.push(q); await this.state.storage.put('queue', JSON.stringify(this._queues)); } } • “マルチユーザーのシングルトンク ラス”のように書ける • サーバーレスでありながら、一意 のクラスインスタンスのように振る 舞う • DBやKVStoreではなく In-memory stateにデータ保持 • 衝突はCloudflare側でキュー管 理してくれる
認証 • Firebase JS SDKを利用 ◦ Authentication, Firestore, Realtime Database,
Storageのみ 利用可能 ◦ react-native-firebase の利用も検討したが、prebuildで苦労した ◦ Firebase Crashlyticsを使わずにSentryを使うことにした • Cloudflare Access を導入してみたい
位置情報 • expo-location を利用
地図表示 • react-native-maps を利用 ◦ GoogleMapsAPIの設定が必要 ◦ Web対応していないので、パッチ処理を行う ▪ https://stackoverflow.com/questions/76629674/unable-to-resolve-utilities-platform-error-with-metro-bundler
• Expo SDK 51ではGoogle MapsがiOSでサポートされず、Apple Mapsに置換された ◦ provider={PROVIDER_GOOGLE} を削除する ◦ https://github.com/expo/expo/issues/28705
ユーザプロフィールの編集 • react-hook-form を利用 ◦ register を使って書けない(?) control を使う export
default function App() { const { control, handleSubmit, formState: { errors }, } = useForm({ defaultValue : { firstName: "", }, }) const onSubmit = (data) => console.log(data) return ( <View> <Controller control ={control} rules ={{ required: true, }} render ={({ field: { onChange, onBlur, value } }) => ( <TextInput placeholder ="First name" onBlur ={onBlur} onChangeText ={onChange} value ={value} /> )} name ="firstName" /> {errors.firstName && <Text>This is required. </Text>} </View> ) }
画像のアップロード • expo-image-picker を利用 ◦ blobだと送信できず、 右記のような形で送信する らしい ◦ 詳細は、
https://www.simpletraveler.jp/2021/09/30/%E3%80%90reactnative%E9%96%8B%E7% 99%BA%E3%80%91formdata%E3%81%A8%E3%81%9D%E3%82%8C%E3%81%AB%E9%9 6%A2%E3%82%8F%E3%82%8B%E6%8A%80%E8%A1%93fetchxhrmultipart-form-data- %E3%82%92%E7%90%86%E8%A7%A3/ const permissionResult = await ImagePicker .requestMediaLibraryPermissionsAsync (); const result = await ImagePicker .launchImageLibraryAsync ({ mediaTypes: ImagePicker .MediaTypeOptions .Images, allowsEditing: true, aspect: [1, 1], quality: 1, }); const uri = result.assets[0].uri; const mimeType = result.assets[0].mimeType; const fileExt = uri.split(".")[uri.split(".").length - 1]; const formData = new FormData(); formData.append("file", { uri, name: `image.${fileExt}`, type: mimeType, }); const res = await fetch(uploadUri, { method: "POST", body: formData, });
プッシュ通知 • expo-notifications を利用 • expo-server-sdk-node でバックエンド実装 ◦ Cloudflare Worker
の Node.js Compatible モードがうまく機能 せず、Node.js API でエラー ▪ assert は自分で書いた ▪ zlib は pako に置換
WebSocket通信 • 標準ライブラリのWebSocketを利用 ◦ バックグラウンドからの復帰で接続切れを起こす ▪ react-native の AppStateを監視して、フォアグラウンドに戻っ た時に再接続を実行
• Cloudflare DurableObjects に WebSocket Hibernation API があ り、WebSocketがお得に使える!
UIライブラリ選定 Expo SDK 51 で使えるもの • React Native Paper •
Tamagui 使えなかったもの • RNUILib • React Native Base ⇒ ビルドまで含めてテストすべき