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
TypeScriptから使いやすいFirestore-simpleを紹介します(2020年版)
Search
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
430
GitHubの新機能とGHESのリリースノートの対応をまとめ続けている話
kesin11
0
210
CircleCIでLayer Cachingを使わずにdocker buildを高速化する
kesin11
3
2.3k
CI/CDのボトルネックを把握できていますか?BigQueryでビルド情報ダッシュボードを構築した話
kesin11
7
11k
GitHub Actionsが他のCIサービスと比較してできることできないこと
kesin11
1
1.8k
iOSアプリのリジェクトリスクを早期に発見するための取り組み
kesin11
4
18k
BitriseでFastlane/Gradleプラグインの統合テスト
kesin11
0
3.5k
Firebase Test Labの紹介
kesin11
4
1.6k
Cloud Functions × BigQuery
kesin11
5
2.5k
Other Decks in Programming
See All in Programming
個人開発者よ、Honoを使え(おじさんver)
tanahiro2010
2
250
APNsからLive Activityを開始する話
yumnumm
0
170
機械に任せるテスト、人が見るテスト ⽣成AIで引き直した、運⽤保守フェーズの線引き
dske104
0
180
Domain-Driven Transformation
hschwentner
2
2.3k
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
590
Are APIs Still Relevant in the AI Era?
soyuka
0
460
パーソナライズPodcastを作った話
repunit11
0
140
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Rails World 2026, Austin, Texas
marcoroth
0
210
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
170
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
380
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.5k
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
210
Featured
See All Featured
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
700
Balancing Empowerment & Direction
lara
6
1.3k
Large-scale JavaScript Application Architecture
addyosmani
516
110k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
7k
Optimising Largest Contentful Paint
csswizardry
37
4k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
520
How to train your dragon (web standard)
notwaldorf
96
6.9k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
430
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
4
4.4k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
350
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
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を作った