Blog

Kotlin でかんたんにインタラクティブなウェブアプリを書ける kweb とは結局なんなのか?

一般的なウェブアプリというのは、クライアントサイドを JS で書いて、サーバーサイドを kotlin 等の別の言語で書く、といったアプローチが一般的です。 このアプローチになるのは、基本的にクライアントサイドでは JavaScript で書く必要があるからです。近年では JavaScript に transpile したりwasm で動かしたりといろんなアプローチが生まれています。 kotlin 界隈でも kotlin/js を react で動かすなど、様々なアプローチが行われています。

一般的なこの方式では、クライアントサイドとサーバーサイドでのコードの共有が難しかったり、接続部分のコーディングが面倒だったりします。

一方 kweb では、クライアントサイドで動くコードを書くから大変なんだ!クライアントサイドで動くコードを書くのが大変なら全部サーバーサイドで動かせばいいじゃない!というアプローチをとっています。 ブラウザ上でのイベント発生時にサーバー側に通信を行って、サーバー側で処理します。そして、サーバー側で DOM を操作すれば、それがクライアントサイドに伝搬する感じになっています。 これらの通信を都度都度行うと高コストなので、websocket で通信を張りっぱなしにしています。 これはなんというか、まぁ通信コスト等も高いですし、富豪的プログラミング だなぁ、という感じですね! 富豪的ではありつつも、めちゃくちゃ簡単にインタラクティブなウェブページを宣言的に書くことができて楽しいです。僕のこのブログの編集画面も kweb で書かれていますが、以前の spring webmvc で書かれていたバージョンに比べると圧倒的にいじりやすくなっていますし、SPA をめちゃくちゃ簡単に実装できるようになっています。

たとえば、簡単な web chat システムを書く場合、以下のように書くだけ。client side と server side の通信プロセスは隠蔽されています。ObservableList に入れたものは、それを watch しているページを表示しているクライアントがあれば、それらすべてに websocket で描画の更新内容が伝搬されます。 実際にどういうふうに通信されてるかは chrome の inspector などで見るのが良いです。

import kweb.ButtonType
import kweb.InputElement
import kweb.InputType
import kweb.Kweb
import kweb.button
import kweb.form
import kweb.input
import kweb.li
import kweb.new
import kweb.state.KVar
import kweb.state.ObservableList
import kweb.state.renderEach
import kweb.ul

val list = ObservableList<String>()

fun main() {
    Kweb(port = 16097) {
        doc.body.new {
            lateinit var inputElement: InputElement
            lateinit var input: KVar<String>

            form {
                inputElement = input(type = InputType.text)
                input = inputElement.value

                button(type = ButtonType.submit)
                    .text("Tweet")
            }.on(preventDefault = true).submit {
                list.add(0, input.value)
                inputElement.setValue("")
            }

            ul {
                renderEach(list) { msg ->
                    li().text(msg)
                }
            }
        }
    }
}

一方で、サーバーサイドで state を持つことによる弊害もあります。 現行バージョンではサーバー側が再起動した場合の挙動がまだちょっと怪しいかもです。あと、Load balancer で sticky session にしないといけないですね。同じインスタンスに常にいかないといけないので。 あとドキュメントがちょっと荒削りだったりとか、まだまだ伸びしろがあるフレームワークだなーという感じ。

業務で使うにはまだちょっと早いかな、という感じはしつつ、考え方は面白いかなーと思うので最近これで遊んでいるというワケ。 コードベースも非常に小さいんで気軽にイジれるし。