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
TypeScriptから使いやすいFirestore-simpleを紹介します(2020年版)
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Kenta Kase
June 26, 2020
Programming
2.2k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
TypeScriptから使いやすいFirestore-simpleを紹介します(2020年版)
2020/06/26 Firebase Realtime Meetup
https://firebase-community.connpass.com/event/175985/
Kenta Kase
June 26, 2020
More Decks by Kenta Kase
See All by Kenta Kase
GitHub Actionsオタクによるセルフホストランナーのアーキテクチャ解説
kesin11
0
400
GitHubの新機能とGHESのリリースノートの対応をまとめ続けている話
kesin11
0
190
CircleCIでLayer Cachingを使わずにdocker buildを高速化する
kesin11
3
2.3k
CI/CDのボトルネックを把握できていますか?BigQueryでビルド情報ダッシュボードを構築した話
kesin11
7
10k
GitHub Actionsが他のCIサービスと比較してできることできないこと
kesin11
1
1.7k
iOSアプリのリジェクトリスクを早期に発見するための取り組み
kesin11
4
17k
BitriseでFastlane/Gradleプラグインの統合テスト
kesin11
0
3.4k
Firebase Test Labの紹介
kesin11
4
1.6k
Cloud Functions × BigQuery
kesin11
5
2.4k
Other Decks in Programming
See All in Programming
Technical Debt: Understanding it Rightly, Engaging it Rightly #LaravelLiveJP
shogogg
0
200
net-httpのHTTP/2対応について
naruse
0
450
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.6k
Oxcを導入して開発体験が向上した話
yug1224
4
290
AI駆動開発勉強会 広島支部 第一回勉強会 AI駆動開発概要とワークショップ
hayatoshimiu
0
450
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
310
These Five Tricks Can Make Your Apps Greener, Cheaper, & Nicer
hollycummins
0
280
ふつうのFeature Flag実践入門
irof
7
3.6k
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
110
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
260
AI駆動開発で崩れていくコードベースを立て直す
kyoko_nr_nr
1
440
Oxlintのカスタムルールの現況
syumai
6
1k
Featured
See All Featured
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.1k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.3k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
200
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.3k
Everyday Curiosity
cassininazir
0
220
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
2.8k
Docker and Python
trallard
47
3.9k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
How to Talk to Developers About Accessibility
jct
2
220
Paper Plane (Part 1)
katiecoart
PRO
0
8.7k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
360
Transcript
TypeScriptから使いやすいFirestore-simpleを紹介します(2020年版) Firebase Realtime Meetup (2020/06/26) @Kesin11
⾃⼰紹介 @Kesin11 (GitHub/Twitter) 本業 組織横断でテストやCI/CDの調査・サポートなど (おそらく普通よりは)CIマニアの気がある Firebaseはプライベート開発がメイン 2019年のアドベントカレンダーでエミュレータを使ったテストの書き⽅を紹介 Firebase Emulator
Suiteをフル活⽤してTDDで開発しよう 2
はじめに この発表はFirestoreの機能は⼀通り知っている前提で話します 質問はYouTubeのコメントにお願いします! 発表中に答えきれなかったらTwitterの#FJUGあたりで回答するかも? 放送後はFJUGのSlackで質問して頂ければ回答できます 3
TypeScriptでFirestoreのコード書くときどんな感じのコードになりますか?
多分こんな感じ? type User = { name: string, age: number, }
const alice: User = { name: 'alice', age: 20 } const docRef = await firestore.collection('users').add(alice) const snapshot = await firestore.collection('users').doc(docRef.id).get() const user = snapshot.data() as User // ここでキャストして型を付ける 毎回collectionを書くのが⾯倒くさい 毎回data()を書くのが⾯倒くさい 毎回キャストで型を付けるのが⾯倒くさい 気軽にキャストしていくのは型ミスに繋がる 5
⾃分でUserCollectionクラスを作ろう class UserCollection { collection: CollectionReference constructor (firestore: Firestore) {
this.collection = firestore.collection('users') } async fetch (userId: string) { const snapshot = await this.collection.doc(userId).get() return snapshot.data() as User } } const userCollection = new UserCollection(firestore) // id='alice' を渡すだけ const user = await userCollection.fetch('alice') 6
⾃分でUserCollectionクラスを作ろう 初期の頃に⾃分が取っていたアプローチ collectionやdata()を毎回書かなくて済む キャストする場所が集約される コレクション毎に似たようなクラスを作る必要がある? 汎⽤化したクラスを作れば全コレクションで使いまわせそう Firebaseプロジェクト毎に汎⽤化したクラスをコピペで持ってくる? -> ライブラリ化しよう 7
Firestore-simple https://github.com/Kesin11/Firestore-simple
Firestore-simpleの思想 . 冗⻑なコードを省く . 強⼒な型推論と補完 . 素のFirestoreのAPIから乖離しすぎない . 間違いを起こしやすい機能へのサポート 9
1. 冗⻑なコードを省く
サンプルケース: FirestoreとTypeScript側でキー名や型が微妙に違う場合 Firestore側 /users : { name: string, age: number,
created_at: Timestamp } TypeScript側 User: { name: string, age: number, createdAt: Date } こういうケース、たまにありませんか? (むしろ皆さんが普段どうやっているのか知りたい) Firestore-simpleはこういう処理を上⼿く実現できます 11
素のFirestoreで書く場合 type User = { name: string, age: number, createdAt:
Date, // js のDate 型で扱いたい } const snapshot = await firestore.collection('users').doc(docRef.id).get() const data = snapshot.data() if (!data) return const user = { name: data.name, age: data.age, createdAt: data.created_at.toDate() // キー名を変換しつつ、Date 型に変換 } as User // 型を揃えたのでここでキャスト 12
Firestore-simpleで書いた場合 ライブコーディングします
Firestore-simpleで書いた場合 type User = { // id は必須プロパティ id: string,
name: string, age: number, createdAt: Date, } type UserFirestore = { name: string, age: number, created_at: Date, } const firestoreSimple = new FirestoreSimple(firestore) const userCollection = firestoreSimple.collection<User, UserFirestore>({ path: 'users', decode: (doc) => { return { id: doc.id, name: doc.name, age: doc.age, createdAt: doc.created_at.toDate() } } }) const user = await userCollection.fetch('alice') // => { id: 'alice', name: 'alice', // => age: 20, createdAt: 2020-06-20T13:12:54.816Z } 14
Firestore-simpleで書いた場合 collectionのpathを指定するのは⼀度だけ fetchした結果にUser型が⾃動で付く Firestore -> js での変換処理(decode)を書くのも⼀度だけ decode: (doc) =>
{} の中で doc も型推論されているので補完が効く(今回は 詳しい説明は省略) 逆⽅向のjs -> Firestoreの変換は encode: (obj) => {} (今回は省略) 型に id を必須にしているのは data() をなくしたゆえの制約 id と他のプロパティを同じようにアクセス可能にするため 先の例: user.id (FirestoreのdocumentId), user.name , user.age 15
その他よく使うと思われる機能のショートハンド fetchAll bulkAdd , bulkSet , bulkDelete batchによる⼀括更新処理のラッパー // batch
でset await userCollection.bulkSet([ { id: 'alice', name: 'alice', age: 20 }, { id: 'bob', name: 'bob', age: 22 }, ]) // colletion の全ドキュメントを取得 const users: User[] = await userCollection.fetchAll() // batch でdelete await userCollection.bulkDelete(users.map((user) => user.id)) 16
2. 強⼒な型推論と補完
現代ではwithConverterを使うという⼿がある data() の結果に型が付く。Firestore <-> jsの変換も可能 Firestore-simpleの開発を始めた2018年頃にはなかった const userConverter = {
toFirestore (user: User): FirebaseFirestore.DocumentData { return { name: user.name, age: user.age, created_at: user.createdAt } }, fromFirestore ( data: FirebaseFirestore.DocumentData): User { return { name: data.name, age: data.age, createdAt: data.created_at.toDate() } } } const userCollection = firestore.collection('users').withConverter(userConverter) await userCollection.doc('alice').set({ name: 'alice', age: 20, createdAt: new Date() }) const snapshot = await userCollection.doc('alice').get() const user: User | undefined = snapshot.data() 18
Firestoreを扱う上でバグが起きやすいのは? (個⼈的には)キー名のtypoという凡ミスが多い docRef.update({ nama: 'bob' }) collection('user').where('aga', '>=', '20') これらはwithConverterでは防ぐことができない
withConverterを通したとしても update や where はキー名までチェックしてくれない 19
Firestore-simpleでは型から抽出されるキー名で補完が可能 ライブコーディングでお⾒せします SpeakerDeckで⾒てる⽅は過去記事のGIFアニメをどうぞ TypeScriptからFirestoreを使いやすくするfirestore-simple v4をリリースしました
3. 素のFirestoreのAPIから乖離しすぎない
ActiveRecord⾵にはしない // 擬似コードです const user = new User user.name =
'alice' user.age = 20 await user.save() // ここでDB に書き込まれる const alice = await User.findBy({ name: 'alice') // DB からデータ取得 素のFirestoreと使い⽅がかなり異なる 何かエラーが起きた場合にユーザーがデバッグするのが⼤変になりそう Firestoreのアップデートに追従して機能追加していくのも⼤変そう 22
外しやすいライブラリを⽬指す あくまでFirestoreの補助 使い⽅を⼤きく変えるライブラリは外しにくくなる 外しにくい=採⽤しにくい 個⼈的なポリシー jsでまだドラフト中の新しい構⽂は使わない(デコレータとか) そもそもFirestoreがもっと便利になれば⾃作して⾃分が使う理由もなくなる withConverterが来たときは開発をやめるか⼀瞬悩みましたが、⾃分にとってはまだ 代替に⾄るものではなかった 23
4. 間違いを起こしやすい機能へのサポート batch transaction
batch const userCollectionRef = firestore.collection('users') const batch = firestore.batch() batch.set(userCollectionRef.doc('alice'),
{ name: 'alice', age: 20 }) batch.set(userCollectionRef.doc('bob'), { name: 'bob', age: 22 }) await batch.commit() 個⼈的に気に⼊らない点 transactionと挙動が似ているのに、runTransactionとAPIが全く異なる set, update, deleteの使い⽅が普通と異なる addが存在しない doc() とidを空にすると裏でランダム値を⼊れてくれるのでaddは実現可能 なぜ⽤意してくれない・・・ 25
Firestore-simpleによるbatchのサポート 単に配列を⼀括処理したい場合は bulkAdd , bulkSet , bulkdDelete runTransactionと同じように書ける runBatch も⽤意
await firestoreSimple.runBatch(async (_batch) => { await userCollection.set({ id: 'alice', name: 'alice', age: 20 }) await userCollection.set({ id: 'bob', name: 'bob', age: 20 }) await userCollection.add({ name: 'random', age: 20 }) }) // <- runBatch を抜けるタイミングで⾃動的にbatch.commit() される runBatch の中ではsetなどはすべて⾃動的にbatch内処理として扱われる うっかりbatch外処理として実⾏してしまうミスは起きない 26
Firestore-simpleによるtransactionのサポート runTransactionもrunBatchと同じ改良がされている add, set, update, deleteは⾃動的にtransaction処理として扱われる transactionはgetも同様 ⼀部の処理だけtransaction外で⾏ってしまうという危険なミスは起きない await firestoreSimple.runTransaction(async
(_tx) => { await userCollection.fetch('alice') await userCollection.fetch('bob') await userCollection.set({ id: 'alice', name: 'alice', age: 20 }) await userCollection.set({ id: 'bob', name: 'bob', age: 22 }) }) // <- runTransaction を抜けるタイミングで⾃動的にtransaction.commit() される 27
Firestoreの新しめの機能もカバーしてます FieldValue.serverTimestamp FieldValue.increment CollectionGroup where INなど Firestore Emulator Firestore-simple⾃体のテストがemulatorで実⾏されているのでバッチリ
最近のv7のアップデート
最近のv7のアップデート Web SDKにも対応しました! v6以前とはインストール⽅法から変わりました npm i firestore-simple はDEPRECATED Admin SDK,
Cloud Function⽤ npm i @firestore-simple/admin Web SDK⽤ npm i @firestore-simple/web 30
Firestore-simpleのターゲットユーザー TypeScriptで型をちゃんと付けたい 使い⽅が素のFirestoreから⼤きく変わらない⽅が好み UIフレームワークとは疎結合にしたい Firestore層のテストを書きたい Firestore-simple⾃体のテストコードをぜひ参考に 31
今後の予定 Web SDKの⼀部機能のサポートができていないので対応したい getやonSnapshotなどWeb SDKのみ存在するオプションにまだ未対応 APIドキュメント⽣成 TypeScriptで流⾏りのドキュメント⽣成ツールを知りたい Firestoreに新機能が来たら対応したい 今年はIOがなかったのでいつ来るのだろう 32
付録1 ドキュメント https://github.com/Kesin11/Firestore-simple/blob/master/README.md サンプルコード(AdminとWebで別々にあります) https://github.com/Kesin11/Firestore- simple/tree/master/packages/admin/example https://github.com/Kesin11/Firestore- simple/tree/master/packages/web/example
付録2 過去記事 v7をリリースしたので改めてfirestore-simpleを紹介します firestore-simple v5をリリースしました TypeScriptからFirestoreを使いやすくするfirestore-simple v4をリリースしました Firestoreをもっと⼿軽に使えるfirestore-simpleがバージョン2になりました Firestoreをもっと⼿軽に使えるfirestore-simpleを作った