山田の近況
- 株式会社テンクーにて、管理画面のフロントエンドをcljsで書く仕事(Clojure仕事!)を何件かやらせていただいた
そこで
- 自分が感じた「cljsでwebアプリを書く際の問題点」をまとめてみた
問題点#1
dom操作が厄介
- cljs固有の問題ではないけれど、厄介なものは厄介
- dom操作は種々のバッドノウハウの塊であり、昔から各種様々なdom操作用フレームワークが作られてきた
(要はjQuery等のジャンル)
dom操作用フレームワーク?
- 先に挙げたdominaもdom操作用ライブラリ
- dominaはdom本体に由来する各種の問題点への対応がいまいちで、バッドノウハウへの対応作業がそこそこ必要
で
- dom回りのバッドノウハウを吸収してくれる、もっと良いフレームワークが欲しい
- (これには更に条件があり、また後で述べる)
問題点#2
cljsの初期化が重い
- cljsでコンパイルしたjsファイルはサイズが大きく、そのロードに結構なコストがかかる
ページのロード
- ページ移動のないwebアプリなら大した問題ではないが、複数ページを持つwebアプリだとページ移動ごとにcljsの初期化(ロード)が発生し、そこそこストレスになる
対策
- 例えば https://clojurecup.com/
- リンク類は普通にあるが、すべてfragment形式(「#/rules」等)
- これはブラウザからはページ内リンクとして認識されるので、リンクをクリックして移動しても、cljsの初期化は実行されない
- しかし、これはこれで別の問題がある(また後述)
しかし
- 通常であれば、ちょっとぐらいリークしてもページ移動すれば解放されるので、大きな問題にはなるケースは少ない
だが
- 先に書いていた「cljsの初期化が重い」問題を解決しようとしてページ移動をfragment形式にすると、ページ移動に伴う解放がなくなる
- その結果、dom由来のメモリリークが解放されず蓄積していく事に
解決方法#1
バッドノウハウに従う
- 「リークしないようにするには、こう書きます」というような大量のバッドノウハウに従い、手間をかけてリークしないように書く
- とても不毛で面倒な作業なので、できればやりたくない
- しかし、これがdomへの基本的な対応方法となる
解決方法#2
ページ移動なしの小さいwebアプリにする
- 要件の大きさを自分で決められるケースは稀だが、小さくできるならそれに越した事はない
- この場合でもリーク対策が必要にはなる
解決方法#3
普通にページを分けて作る
- cljs初期化コストについては諦める
- ページ移動ごとのロードが重い点を除けば良好
解決方法#4
domのバッドノウハウを吸収してくれるフレームワークを採用する
- 条件は「適当に書いてもdomがメモリリークしない」
「扱いやすい」「domのかゆいところに手が届く」
あたり。かなり厳しい - Omベースの優秀フレームワークをそのうち誰かが作る気がする(無責任)
解決方法#5
canvasに引きこもり、domに関わるのは最小限にする
- 個人的には、作りたいものはwebアプリではなくブラゲ(ブラウザゲーム)なので、canvasに引きこもる事が可能
- しかし、もちろん仕事となれば、そうは行かない
- またcanvasにもバッドノウハウはそれなりに必要
以上
- 個人的には「canvas引きこもり」を選択する
- 仕事をする場合にどうするかは悩ましいところ
- 直近の仕事では「普通にページを分けて作る」事を選択したが、「ページ移動ごとのロードどうにかしたいなあ」とは思っていた
長期的には
- 近未来に、優秀フレームワークがキラーアプリ的に登場したら、それを採用する
- 別にcljs用ではなくjs用フレームワークでもよいです、コード品質さえちゃんとしていれば
まとめ#1
問題点は以下の三つ
- domはバッドノウハウの塊
- cljsページ開くの遅い
- メモリリーク
まとめ#2
解決策は以下の六つ
- 地道にバッドノウハウ対応
- 未来の優秀フレームワークを採用
- 「#/link」形式にして、ページのリロードを避ける
(デメリットあり) - 要件規模を小さくし、可能ならページ移動なしの実装に
- cljsページ開くの重い問題については諦めてもよい
- domを捨て、canvasに引きこもる
その後
- このスライド発表後に、react-canvasを@tnoda_さんに教えてもらった
- canvas上に仮想domを描画するらしい
- 文字列のコピペができない等の欠点はありそうだけど、悪くはなさそうな雰囲気なので、後で試してみたい