cljsでwebアプリを書く際の問題点

by 技情研ネット 山田
at ATC Clojure (2015/02/21)
(更新日時 2015/02/23)

山田の近況

  • 株式会社テンクーにて、管理画面のフロントエンドをcljsで書く仕事(Clojure仕事!)を何件かやらせていただいた

どんな感じ?

  • 管理画面の内容は、cratedominaでdomの生成と操作を行い、core.asyncでコールバック地獄を避けつつ、cljs-ajaxでサーバサイドのclj部と通信する、みたいな感じ

そこで

  • 自分が感じた「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の初期化は実行されない
  • しかし、これはこれで別の問題がある(また後述)

問題点#3

メモリリーク

しかし

  • 通常であれば、ちょっとぐらいリークしてもページ移動すれば解放されるので、大きな問題にはなるケースは少ない

だが

  • 先に書いていた「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を描画するらしい
  • 文字列のコピペができない等の欠点はありそうだけど、悪くはなさそうな雰囲気なので、後で試してみたい