Slide 1

Slide 1 text

2024/09/24 Kotlin愛好会 vol.54    にしこりさぶろ〜(@subroh_0508)    Compose for Webで ポートフォリオサイトを作る

Slide 2

Slide 2 text

自己紹介 2 【¥303,075】にしこりさぶろ〜 @subroh_0508 🎤経歴 1995年生まれ。東京の離島・伊豆大島出身。 メインの技術スタックはKotlin・Android・Rails・React。 ● 2016年3月 東京高専 情報工学科卒 ● 2016年4月 株式会社TOKIUM入社(当時はBearTail) 2016年4月 💼Android/Webエンジニア ● 2023年1月 DevHRにロールチェンジ 2023年1月 💼エンジニア採用・組織作り・採用広報 ● Now!! 新卒9年目、プレイヤーとして6年8ヶ月 その後、人事職にロールチェンジして2年目

Slide 3

Slide 3 text

自己紹介 3 【¥303,075】にしこりさぶろ〜 @subroh_0508 💖趣味 ああああああああああああああああとアイドルマスター。 Kotlin本体へのContribute経験、Kotlin Festへの登壇経験 アリ(2019、2022、2024)。DevHRになって以降は開発 業務から離れたが、趣味でKotlinを書き続けている。 アイドルマスターが好きすぎて、ライブがあれば全国どこに でも飛び、ほぼ月1回の頻度で現地会場に現れる。昨年末の 異次元フェスで脳が破壊され、最近ラブライバーになった。 Kotlin Fest 2024登壇時

Slide 4

Slide 4 text

🔧自身のポートフォリオサイト 初代: Kotlin/JS + React.js 2代目: Compose HTML (Kotlin/JS) 3代目: Compose for Web (Kotlin/Wasm) 初回リリースは2019年5月! WebアプリをフルKotlinで 実装する謎の縛りプレイを 5年以上続けている😂 4 subroh0508.me subroh0508/portfolio 自己紹介 / どのくらいKotlinが好きか Now!!

Slide 5

Slide 5 text

🌟 Compose for WebでどんなWebアプリが実装できるのか紹介 ➔ Compose for Web製のWebアプリでできること、嬉しいこと ➔ 実装の上で困ったことをどう乗り越えたか ➔ 現状のCompose for Webの障壁、使いどころについて 5 今日話すこと

Slide 6

Slide 6 text

6 🤔 Compose Multiplatformとは ➔ AndroidアプリのUIを宣言的に実装できるJetpack Composeの Kotlin Multiplatform対応版 ➔ iOS・Desktop・WebアプリのUIを1つのコードで宣言的に実装できる! 公式サイト: Compose Multiplatform UI フレームワーク | JetBrains Desktop向けは既に安定版に到達! iOS向けも、実はα版までリリースされている! 前提知識: フレームワークについて Androidに加え

Slide 7

Slide 7 text

7 🌐 Compose HTML Kotlinコードが最終的にJavaScriptコードに変換される 👍 情報・ライブラリ資産が豊富(=JavaScriptの情報・ライブラリが転用可) 👎 見た目の調整にCSSを利用するため、UI実装を他ターゲットと共通化できない 🤖 Compose for Web Kotlinコードが最終的にWebAssemblyコードに変換される 👍 他ターゲットと同じ仕組みで見た目を調整でき、UI実装の完全な共通化を実現 👎 ビルド後のファイルサイズが大きい、DOMへのアクセスに制限がある 前提知識: Compose MultiplatformでのWebアプリ実装方法

Slide 8

Slide 8 text

8 🌐 Compose HTML Kotlinコードが最終的にJavaScriptコードに変換される 👍 情報・ライブラリ資産が豊富(=JavaScriptの情報・ライブラリが転用可) 👎 見た目の調整にCSSを利用するため、UI実装を他ターゲットと共通化できない 🤖 Compose for Web Kotlinコードが最終的にWebAssemblyコードに変換される 👍 他ターゲットと同じ仕組みで見た目を調整でき、UI実装の完全な共通化を実現 👎 ビルド後のファイルサイズが大きい、DOMへのアクセスに制限がある 前提知識: Compose MultiplatformでのWebアプリ実装方法 今日はこちらにフォーカス🔎

Slide 9

Slide 9 text

9 Compose for Webでできること 💻動作デモ subroh0508.me subroh0508/portfolio

Slide 10

Slide 10 text

10 Compose for Webでできること 💻動作デモ ➔ ライトテーマ・ダークテーマ切り替え ➔ ナビゲーション(URLのパスと画面が紐づく) ➔ 各種アニメーション(Fade In/Out、Ripple Effect) ➔ CSSを一切書かずに実装 subroh0508.me subroh0508/portfolio 状態を持たないシンプルな Webアプリとして 十分な機能が実現できている💪

Slide 11

Slide 11 text

11 Compose for Webでの困りごと 😣 ここまで実装する上で困ったこと

Slide 12

Slide 12 text

12 Compose for Webでの困りごと 😣 ここまで実装する上で困ったこと(1/3) ➔ 外部リンクにジャンプできない! 通常、 タグを使えば、何も考えることなく実現できるが… X.com

Slide 13

Slide 13 text

13 Compose for Webでの困りごと 😣 ここまで実装する上で困ったこと(1/3) ➔ 外部リンクにジャンプできない! 通常、 タグを使えば、何も考えることなく実現できるが… Compose for WebはDOM操作・HTML出力をしないので タグを使った外部リンクへのジャンプができない🫠 X.com

Slide 15

Slide 15 text

😣 ここまで実装する上で困ったこと(3/3) ➔ 日本語フォントがtofuになる! 15 Compose for Webでの困りごと 修正前の状態😇

Slide 16

Slide 16 text

16 Compose for Webでの困りごとを乗り越える(1/3) 😣 外部リンクにジャンプできない! ➔ Kotlinの標準ライブラリにBrowser APIのラッパーメソッドが存在 これは、Kotlin/Wasmからも呼び出すことが可能! fun openWindow(url: String, target: String) { window.open(url, target) } window.open を呼び出すメソッドを定義

Slide 17

Slide 17 text

17 Compose for Webでの困りごとを乗り越える(1/3) 😣 外部リンクにジャンプできない! ➔ Kotlinの標準ライブラリにBrowser APIのラッパーメソッドが存在 これは、Kotlin/Wasmからも呼び出すことが可能! fun openWindow(url: String, target: String) { window.open(url, target) } @Composable fun AccountLink( label: String, href: String, ) = FilterChip( selected = true, onClick = { openWindow(href) }, leadingIcon = { icon() }, label = { Text(label) }, ) window.open を呼び出すメソッドを定義 → 引数 onClick に渡せばOK👍

Slide 18

Slide 18 text

18 Compose for Webでの困りごと(2/3) 😣 クリック可能なコンポーネントでマウスカーソルが変化しない! ➔ Modifierでホバー時のカーソルを指定してあげる @Composable fun AccountLink( label: String, href: String, ) = FilterChip( selected = true, onClick = { openWindow(href) }, label = { Text(label) }, modifier = Modifier.pointerHoverIcon(PointerIcon.Hand), ) pointerHoverIcon で、ホバー時のカーソルを変えられる! Default / Crosshair / Hand / Textの4種類に対応

Slide 19

Slide 19 text

19 Compose for Webでの困りごと(2/3) 😣 クリック可能なコンポーネントでマウスカーソルが変化しない! ➔ Modifierでホバー時のカーソルを指定してあげる @Composable fun AccountLink( label: String, href: String, ) = FilterChip( selected = true, onClick = { openWindow(href) }, label = { Text(label) }, modifier = Modifier.pointerHoverIcon(PointerIcon.Hand), ) pointerHoverIcon で、ホバー時のカーソルを変えられる! Default / Crosshair / Hand / Textの4種類に対応

Slide 20

Slide 20 text

😣 日本語フォントがtofuになる! ➔ コード内で明示的に日本語フォントを読み込ませる 20 Issue #3967 Compose for Webでの困りごと(3/3) private val fontSets: List = listOf( FontSet("NotoSansJP-Medium.ttf", FontWeight.Medium, FontStyle.Normal), // 略 ) @Composable fun rememberFontFamily(): FontFamily { val fontFamily = remember { mutableStateOf(listOf()) } LaunchedEffect(Unit) { fontFamily.value = fontSets.map { val byte = loadBytesFromPath("fonts/${it.fileName}") Font(it.fileName, byte, it.weight, it.style) } } return FontFamily(fontFamily.value) } Noto Sansフォントを 読み込むコード

Slide 21

Slide 21 text

😣 日本語フォントがtofuになる! ➔ とりあえずNoto Sans JPフォントをウェイトごとに全て読み込ませたところ… 21 Compose for Webでの困りごと(3/3) Wasmファイルの読み込み完了から 文字の表示までに2分かかる 激重ポートフォリオサイトが爆誕😂 対応時のIssue

Slide 22

Slide 22 text

22 😣 日本語フォントがtofuになる! ➔ 軽量なM PLUS 1pに差し替え + 未使用文字を除外したカスタムフォントを用意 Wasmファイルの読み込み完了から 1秒以内に文字が表示されるように🎉 Compose for Webでの困りごと(3/3) 対応時のIssue

Slide 23

Slide 23 text

😭 Wasmファイルの読み込みが重い ➔ Compose for Webの動作に必要な、UIレンダリングエンジン「Skia」 Skiaを動かすために必要なWasmファイルのサイズが2.5MBもある! 23 現状の障壁 これが大きいと、他でどんなに頑張っても 初回ローディングが遅くなってしまう😇

Slide 24

Slide 24 text

😭 埋め込みリンクが使えない ➔ Canvas要素に描画をしているため、各種Webサービスの埋め込みリンクを 利用することができない! 24 現状の障壁 漢気すら感じる、 非常にシンプルなHTML👊 推し曲のYouTube・Spotifyのリンクが貼れない😢 ※右のスクショはNotionでの例

Slide 25

Slide 25 text

😭 Safariで表示できない ➔ Webkitが未対応!現在開発中! 25 なお、JetBrainsのサンプルを真似たら なぜかSafariでも表示できるようになりました🤔 なぜ表示できるのか、理由は現状不明だ!こわい!😂 現状の障壁

Slide 26

Slide 26 text

26 現状の障壁 色々障壁があるっぽいけど、それってCompose for Webが悪いのか??? ただのポートフォリオサイトに、Wasmを使うのが間違いなのでは???

Slide 27

Slide 27 text

27 色々障壁があるっぽいけど、それってCompose for Webが悪いのか??? ただのポートフォリオサイトに、Wasmを使うのが間違いなのでは??? はい、その通りです!😇😇😇 好きでやってるんだから正論パンチすな 現状の障壁

Slide 28

Slide 28 text

🤔 Compose for Webの使いどころ 28 現状の障壁 WebAssemblyは「高いパフォーマンス」や 「複数プラットフォームでの安定動作」が必要な 場面で最も力を発揮する 採用事例: Google Meetの背景ぼかし機能、 Amazon Prime Videoの動画再生クライアント 「主要ブラウザで動作すればOK」であり、 「高いパフォーマンスは必要とされない」 Webサイトへの採用は正直Too Much😇 出典: WebAssembly の概要 - WebAssembly | MDN

Slide 29

Slide 29 text

🤔 Compose for Webの使いどころ ➔ Android / iOS / Desktopアプリが既にあり、Webでも使えるようにしたい! ➔ WebアプリをAndroid / iOS / Desktopでも提供したい! 29 現状の障壁 上記ユースケースでは、大きな価値を発揮する💪 以前作った、スマホを気軽にペンライトにできる WebアプリをCompose for Webで書き直したい…!😊

Slide 30

Slide 30 text

まとめ 30 👍 Compose for Webを使うと、Androidアプリの実装経験を強く活かしながら Webアプリの開発に取り組むことができる! ➔ CSSを使わずにWebアプリを実装できるのは、非常に強力 ➔ 「JavaScriptでのWebアプリ開発と同じことができる!」と思って進めると ハマりどころが多数あるため注意 👍 Compose for Webは、アプリのX-Plat対応において大きな価値を発揮する!(はず) ➔ 「モバイルとWeb、両方欲しい!」ケースに遭遇したら、検討してみては😉 ポートフォリオサイト、簡単なゲーム、効率化アプリ等 まずは小さな開発からCompose for Webを試してみましょう!楽しいぞ!😘 Thank you for listening!