概要(日記)
Kotlin Multiplatform (Kotlin/js)とfirebase-kotlin-SDKでプラウザアプリの骨組みを作る。
前提
- Ubuntu 22.04 on Windwos 11 wsl2
- Firebaseプロジェクト・Firestoreが有効であること
- 認証無し。実験用
Step 1: 空のアプリ作成
build.gradle.kts
plugins {
kotlin("multiplatform") version "2.0.0"
}
repositories {
mavenCentral()
}
kotlin {
js {
browser{}
binaries.executable()
}
}
src/jsMain/kotlin/Main.kt
fun main() {
println("Hello, World!")
}
src/jsMain/index.html
<script src="KtFirestore.js"></script>
src="KtFirestore.js"
はProject名(デフォルトでプロジェクトフォルダ名)に置き換え
実行
sh gradlew jsRun
ブラウザが起動し空のページが表示される。開発者ツールでConsole上にHello, World!
が表示されていることを確認。
Step 2: Firebase Kotlin SDK 組み込み
Firestore SDKは大きく2通り
- Admin SDK: サーバ上で動作するFirestoreアプリ用。サーバ上でAPIを提供する場合
- モバイル/Web SDK: デバイス/ブラウザから直接(APIを介さず)DBにアクセスする場合
プラウザアプリならWeb SDKを使用するのだが、今回せっかくなのでmultiplatformに対応するfirebase-kotlin-SDKを試してみた。
Webページはkotlinx.htmlを使ってHTMLを手書き。
build.gradle.kts
//...
kotlin {
js {
browser {}
binaries.executable()
}
sourceSets {
jsMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core
implementation("dev.gitlive:firebase-firestore:1.13.0") // https://mvnrepository.com/artifact/dev.gitlive/firebase-firestore
implementation("org.jetbrains.kotlinx:kotlinx-html:0.11.0") // https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-html
}
}
}
src/jsMain/resources/index.html
<body></body>
<script src="プロジェクト名.js"></script>
src/jsMain/kotlin/Main.kt
val options = FirebaseOptions(
apiKey = "xxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxx",
projectId = "xxxxxx",
databaseUrl = "https://xxxxxxxxxxxxx.firebaseio.com",
applicationId = "1:xxxxxxxxxxx:web:xxxxxxxxxxxxxxxxxxxx",
)
@OptIn(DelicateCoroutinesApi::class)
suspend fun main() {
val app = Firebase.initialize(Unit, options)
val db = Firebase.firestore(app)
db.settings = firestoreSettings(db.settings) { cacheSettings = persistentCacheSettings { } }
fun addItem(item: String) = GlobalScope.launch { db.collection("tmp").add(mapOf("action" to item)) }
fun delItem(id: String) = GlobalScope.launch { db.collection("tmp").document(id).delete() }
val action = document.create.input(name = "name")
val book = document.create.table()
val body = document.body ?: error("body is null")
body.append(book)
db.collection("tmp").snapshots.collect { qs ->
book.innerHTML = ""
book.tHead = document.create.thead { tr { td {};td { +"To do List" } } }
book.insertRow().apply {
insertCell().append { button { +"Add" }.onclick = { addItem(action.value) } }
insertCell().append(action)
}
qs.documents.forEach { ds ->
book.insertRow().apply {
insertCell().append { button { +"Del" }.onclick = { delItem(ds.id) } }
insertCell().apply { textContent = ds.get<String?>("action") ?: "[No Action]" }
}
}
}
}
apiKeyなどの接続情報は Firebaseポータル→プロジェクトの設定 を参照。
※実際のコードではapiKeyをコミットしてしまわないよう注意。
資料