Compose for Webで始めるWebアプリ開発

:::note warn
追記(2025年6月14日)：この記事はKotlin/JSのCompose for Webに関する記事であり、公式にCompose HTMLと呼称されているAPIの記事となります。
Kotlin/wasmのCompose for Webtお間違えないようご注意ください。
:::

# 初めに
この記事は、[**FUN Advent Calendar 2022**](https://adventar.org/calendars/7402)の9日目の記事となっています。
**弊大の人に読んでもらうことを念頭に置いています。ご了承ください。**

昨日はAtriaの[手を振ったら部屋の電気を消す魔法が欲しい](https://atriasoft.work/posts/magic-hands/)でした。
私もWear OSのアプリ開発してみたいんですよね。
ちなみにPart2は[nickさんの記事](https://hackmd.io/@nick-san/fun_advent_calendar_2022)で、Part3はまりもさんのGPAロンダリング！でした。
私は車を移動手段としてしか見れないので、ここまで情熱を注げるのは素直に尊敬しますね。
GPAロンダリングはまあ、はい。院に進む人とか就活で成績をばっちり見られるって感じなら嬉しいかも...？

おはこんハロチャオ！**json色付け係**こと、[いかの塩辛](https://twitter.com/shiokara_create)もとい[こた](https://twitter.com/kotambourine)です。
突然ですが皆さんは**クソアプリ**を開発していますか？

クソアプリとはその名の通り、社会にとってクソほど有益にならないけれどもクスッと笑える程度のユーモアさでなんとか存在を許されているアプリです。(そんなことはない)
私はITエンジニア、特にフロントエンドエンジニアを名乗りたいと考えている人間には、クソアプリを作ることをおすすめしています。

というのも、クソアプリは
- アプリケーションなので完成した時の達成感がある。
- アプリケーションなので開発中の経験が何かに活きる~~かもしれない~~。
- けど名前からわかるように期待されないので開発のハードルが低い。

このように手っ取り早く自信を得たい、キャッチアップを迅速に行いたいという時にはベターな選択肢と言えるのです。

今回は、Kotlin, Compose for Webという技術を使いながらクソアプリ入門をやっていきましょう。

# アプリ概要
聡明なる読者の皆さんはご存知であろうと思いますが、この世には「**きのこの山**」[^1]という**大変素晴らしいお菓子**が存在します。
きのこを模した形をしており、柄の部分にサクサク感がたまらないクラッカー、傘の部分にミルクチョコレートとカカオが香るチョコレートの二重構造が存在するお菓子となっています。
このお菓子の素晴らしさは、我が校で買い占め[^2]が起こるほどの一大ムーブメントを巻き起こしていることからも窺えるでしょう。

一方、きのこの山の後発として「**たけのこの里**」[^3]と言う類似商品が存在します。
中身がクッキー、外側がチョコレートという大変似通った商品であるため、しばしばきのこの山と比較されることがあります。
好みというのは個人差がありますが、皆さんでしたらどちらの商品がお好きでしょうか？
きのこの山？素晴らしい。たけのこの里？これからきのこの山の素晴らしさに気づけるだなんて羨ましいですね。

さて、つらつらと御託を並べていきましたが、私はこれらの商品を眺めている時、ふと思ったのです。
「**きのこの山は、まるで雨のように降るたけのこの里から身を守る傘のようだな**」と。~~何を馬鹿なことを言っているんだ~~

というわけで今回は「降ってくるたけのこの里をきのこの山でガードしよう」というクソアプリを作っていきます。
都合よくその辺に、昔描いたきのたけのイラストがあったので良かったです。

# 完成形
まずは完成形を見てもらいましょう。
![止まない雨はナッシング.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442889/2a511bd6-1d6b-1bf3-a6a7-5c52d9baab9d.gif)

**なんだこのクソアプリは...**

はい、思ってた以上(以下？)にクソアプリになりました。レスポンシブデザインとか考えてないので、PCでしか遊べません。
(言い訳になりますがCSSまじでわからんのと何故かエディタがライブラリを認識してくれない現象に陥りました。)
[**このページ**](https://kota-shiokara.github.io/yamanai-ame-ha-nothing/) で遊べるので興味があればやってみてください。
AorDキー若しくは左or右矢印キーできのこを動かすことができます。

後ちゃんと実装頑張ったよっていう配信をしました。
**5時間**ずっとカタカタやって「あれれ～？おっかしいぞ～？」とか「CSSなんもわからん」とか言ってるような配信ですが、興味があれば見てやってください。
<br>
<iframe width="560" height="315" src="https://www.youtube.com/embed/NRDko7XBD7I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<br>
<br>
ここからはちょっとした解説編になります。

# 諸注意
説明を一々書いていると果てしなく長くなりそうなので、この先端折ることが多々あります。
- 基本的なHTML, CSSの知識がない人
- Kotlin、Jetpack Composeなんて知らん！

という人には少し難しいところがあるかもしれません。
わからない箇所があれば、[Twitter](https://twitter.com/kotambourine)とかこの記事で質問をしていただけるとできる限り回答したいと思います。

# Jetpack Composeの説明
Jetpack Composeのお話をする前に、Kotlin[^4]に関してお話したいと思います。
Kotlinというプログラミング言語があります。
JVM言語の一種で、Javaと完全互換性を持ったまま、より簡潔で安全であることを目指したプログラミング言語です。
よくAndroidアプリの開発に用いられるため、聞いたことがある人が多いかもしれません。
弊大の人にとってはProcessingの仲間と言った方が馴染みが深いかもしれませんね。

さて、そんなKotlinですが、昨今のクロスプラットフォームという流行に後れず、**Kotlin Multiplatform**[^5]なるものが存在します。
これは通常のクロスプラットフォームとは一味違い、共通化できるとこはKotlinで共通化しちゃおうぜ！という考えが強いことが特徴と言えます。
そのため、Kotlinでは、JVMはもちろんAndroidやDesktopアプリ、Webアプリからサーバーまでこれ一本(と少々のコード)で作ることができるのです。

話をJetpack Composeに戻します。こちらはAndroidアプリ開発でよく使用されるJetpack Libraryの1つで、宣言的UIを可能とするUIライブラリとして注目を集めているナウでヤングな技術となっています。
そしてなんと、Jetpack Composeを基に、クロスプラットフォームという流行に乗じた**Compose Multiplatform**という概念が生まれました。
わざわざUI部分まで共通化って...そんなのKotlin大好きな~~変態~~人間しか触らないじゃないか！

そんなこんなでComposeには、**Compose for Desktop**と**Compose for Web**という仲間？が存在しているのです。
(ややこしいですが、Jetpack ComposeはGoogle製でCompose for ○○はJetBrainsというKoltinを開発した会社が作っています。)

# Compose for Webをやってみる
Compose for Webは、Kotlin/JS for Reactという名の「ReactをKotlinでやりたい」という~~これまた変態的な~~技術の流れを汲んでいるのか、DOMのAPIを使用して画面を構築する形になっています。
具体的なGetting Startedの手順は[**チュートリアル**](https://github.com/JetBrains/compose-jb/tree/master/tutorials/Web/Getting_Started)にお任せするので、そちらをご覧ください。

実際のソースコードを見てましょう。
これはチュートリアルに記載があったものをより簡潔にした、Main.ktです。
```kotlin
fun main() {
    renderComposable(rootElementId = "root") {
        Div({ style { padding(25.px) } }) {
            Text("Hello, World")
        }
    }
}
```

少しHTMLやReactをかじったことがある方はお分かりかと思いますが、上記のようにまるで関数がHTMLのタグのように書くことができます。

他にも、こんなコードが書けます。
```kotlin
fun main() {
    val (count, setCount) = remember { mutableStateOf(0) }
    renderComposable(rootElementId = "root") {
        Button(attrs = { 
            onClick { setCount(count + 1) }
        }) {
            Text("$count")
        }
    }
}
```

そう、React hooksのようなコードですね。(まあReactに近しい書き方をする程度のメリットしかないと思いますが...)

また、これはKotlin/JSのプロジェクトであるため、npmのパッケージを使用することも可能です。[^6]
ビルドツールのGradleを使用するために記述する`.gradle`もしくは`.gradle.kts`ファイルに、必要なパッケージ名とバージョンを記述し、橋渡しとなる関数を定義してあげるとよいでしょう。
```kotlin build.gradle.kts
dependecies {
    implementation(npm("example", "7.7.7"))
}
```
```kotlin example.kt
@JsModule("example")
@JsNonModule
external fun <T> hoge(a: Array<T>, b: Array<T>): Boolean
```

これは余談(な上にめちゃくちゃ技術的なお話)なのですが、先ほど「DOMのAPIを使用して～」ということを書いたと思います。
これどういうことかというと、Compose for Webだけ同じコードでUIを作れないんですね。
Jetpack Compose、Compose for DesktopはレンダリングにSkiaを使用しているため、Androidで書いたコードを移植！とかできるんですが、WebはDOMのAPIベースなので1人ぼっちなのです。
実はそんなCompose for Webにも光明が差し込みました。
experimental(試験的な～とかそんな意味合い)ではありますが、Skia(厳密にはSkiko)を使用して共通化できるようになったのです！！
詳しくは**明日、12月10日**に開催される[**Kotlin Fest 2022**](https://www.kotlinfest.dev/)にて「[**Compose for WebでもDomじゃないCompose UIが使える？**](https://fortee.jp/kotlin-fest-2022/proposal/d41981fb-8853-40ad-b1dd-a49326f0d39c)」というセッションがあるそうなので、気になる方は見てみるといいかも！？？！

# おわりに
さて、Compose for Webの説明を軽くしてみましたがいかがでしょうか。
ReactなどWebフロントエンドを行っている人は馴染みやすいのではないかと思います。
ここまで読んだそこのあなた！これを機会にKotlinもしくはクソアプリ開発に挑戦してみませんか？！？

本当はもっとちゃんとしたクソアプリをサーバー、Web、Android全部Kotlinでイエーイ！ってした記事を書こうと思ってたんですが、Herokuの申請時期を見誤り、Student Developer Packでもらえるクレジットがまだもらえてなくてサーバー立てれなくなってしまい諦めました。
実装の意欲はあるので、やる気があれば記事も書こうかなとか思います。

明日から弊大では[**p2hacks**](https://p2hacks2022.github.io/)という学内ハッカソンが始まります。
今年は出場者も多いしスポンサーも豪華だしで、運営側の私もドキがむねむねしています。

12/10はぺるきくんの「ほぼ知らん技術だけで30日間Web開発デスマーチ」、ハニ・トーさんの「AIチャットに言われた通りに何かを作る(準備編)」、beruの「なんか書く(内容未定)＋就活爆死談」の三本立てです。(12/9現在公表情報より)
ちなみにほんとの初期の初期の案では、ポートフォリオ作るはずだったのでぺるきくんとネタ被りかけてました。

それではこの辺で筆を置こうと思います。お疲れさまでスター！

[^1]: 株式会社 明治 きのこの山 https://www.meiji.co.jp/sweets/chocolate/kinotake/products/kinokonoyama/
[^2]: きのこの山で炎上した件について https://note.com/pote_375/n/n51c42132e2a3
[^3]: 株式会社 明治 たけのこの里 https://www.meiji.co.jp/sweets/chocolate/kinotake/products/takenokonosato/
[^4]: Kotlin Programming Language https://kotlinlang.org/
[^5]: Kotlin Multiplatform | Kotlin https://kotlinlang.org/docs/multiplatform.html
[^6]: Use dependencies from npm | Kotlin https://kotlinlang.org/docs/using-packages-from-npm.html