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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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.7k
iOSアプリのリジェクトリスクを早期に発見するための取り組み
kesin11
4
18k
BitriseでFastlane/Gradleプラグインの統合テスト
kesin11
0
3.5k
Firebase Test Labの紹介
kesin11
4
1.6k
Cloud Functions × BigQuery
kesin11
5
2.4k
Other Decks in Programming
See All in Programming
すこし踏み込む CancellationToken
htkym
2
590
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
190
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
250
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
220
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
250
What We Talk About When We Talk About XP
m_seki
2
660
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
120
Security issues being discussed on Web Platforms
petamoriken
0
980
AHC070解法紹介
eijirou
0
130
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
180
スマート反転とウェブアクセシビリティ
camiha
0
210
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
1
560
Featured
See All Featured
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
260
Ten Tips & Tricks for a 🌱 transition
stuffmc
1
230
KATA
mclloyd
PRO
35
15k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.6k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Visualization
eitanlees
152
17k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
480
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
The Spectacular Lies of Maps
axbom
PRO
1
1k
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を作った