ChatWork Creator's Note

ビジネスチャット「チャットワーク」のエンジニアとデザイナーのブログです。

ChatWork Liveの刷新とScala.jsについて

こんにちは。クライアントアプリケーション開発部の田中です。

好きな麻雀の役は七対子です。

先日、ChatWork LiveのUIが変更されました。 詳細は下記を御覧ください。

blog-ja.chatwork.com

UIについては今後デザイン部の方がブログを書くと思うので、今回私の方では技術的なところの紹介をしたいと思います。

(尚、この記事にはWebRTCやビデオ会議システムの話は全く出てきませんので、ご了承ください。)

ChatWork Liveのフロントエンド技術について

実は今月のUI更新とは別に、JavaScript部分の大幅な変更を4月末に実施しています。

大まかな設計はすべて@kyo_ago氏がやってくれて、 私は敷かれたレールをただただ歩くだけだったので割と楽させてもらいました。

ChatWork LiveのWebクライアント側は主に以下の技術を使って実装されています。

Scala.jsの採用について

今回ChatWorkで初のScala.jsの採用を試みましたが、以下のような目的で採用しました。

  • Scalaの強力な型システムがほしい
  • 弊社には何名かScalaエンジニアがいるので、リソースの再配分できるかも
  • 楽しそう

もちろん、初めて採用するAltJSなのでいくつかの不安要素はありましたが、@kyo_ago氏の無茶振り熱い説得もあったのと、ChatWorkLive自体はJavaScriptの領域でいうと大規模なプロジェクトにもならなそうだったので、採用となりました。

使ってみた感想等については後述します。

構成について

今回のChatWork Liveは大きく分けてView側のみを担当する箇所と、その他のAPI通信やモデルデータの構成等を担当する箇所に分けて実装をしています。 弊社ではよく前者をfrontend-frontend, 後者をfrontend-backendと読んでいます。

今回、frontend-frontend部分をReactのプロジェクトとして、frontend-backend部分をScala.jsのプロジェクトとして、それぞれを実装しました。 両者間のデータのやり取りはpostMessage APIを用いて実現しています。

f:id:tan-yuki:20180813185945p:plain

なぜこのような2つ構成にしたか

Scala.jsを触ったことのある方なら経験があると思いますが、Scala.jsでView部分を構築するのは結構辛いです。 View部分は特に型の恩恵が得にくい部分でもあり、そこまでScala.jsで書くうまみを感じません。

そのため、View部分はViewに特化したライブラリを採用し、通常のJavaScriptプロジェクトとして実装し、 その他をScalaプロジェクトとして書くこととしました。

今回は弊社ではReactを採用していますが、もちろんVue.jsや他のライブラリを用いることも可能です。

パッケージ構成について

パッケージ構成は以下のようになっており、Scala.jsプロジェクトの中にJavaScriptのプロジェクトを内包するような構成をとっています。

.
├── README.md
├── build.sbt
├── project/
│   ├── build.properties
│   ├── plugins.sbt
│   ├── project/
│   └── target/
├── src/
│   ├── main/
│   │   ├── resources/    <- es6 sources
│   │   │   ├── package.json
│   │   │   ├── src/
│   │   │   ...
│   │   │
│   │   └── scala/        <- Scala sources
│   ├── target/
│   └── test/
│       └── scala/
└── target/

buildはsbt buildをすると、Scala.jsプロジェクトのbuildと同時にfrontend-frontend側のbuildも同時に行うようにしています。

フロントエンド全体のアーキテクチャについて

こまかな部分は省略していますが、雰囲気としては以下のような感じです。

f:id:tan-yuki:20180813190010p:plain

  1. UserEventやWebSocket経由でイベントが発火する
  2. 発火したイベントを元にデータが書き換わる、必要ならサーバーサイドAPI経由でデータを取得する
  3. 書き換わったデータを元にレンダリング用のデータを構築し、frontend-frontend側にpostMessageで渡す
  4. frontend-frontend側でViewが構築される

ちゃんとしたFluxの流れではないですが、Fluxっぽくデータが一方方向に流れるような設計となっています。

Scala.jsを採用しての感想

最初に感じていた不安

最初に採用するときにいくつか不安があったと前述しましたが、それらの不安要素はほとんど杞憂でした。 以下、私がScala.jsを導入する以前に感じていた不安要素です。

Q. ファイルサイズ重くならない?

まぁ、多少重くなります。が、そこまで気になるサイズではないかと。 Scala.js側で採用するライブラリによってはかなり大きくなることもあるので、Scala.js側はバンバン外部ライブラリを導入することは避けたほうが良さそうです。

現在の本番buildのJavaScriptのサイズは271KBでした。

Q. なんかよくわからないところでつまづきそう

もちろん何故かコンパイルがエラーになったり、IntelliJがうまく動かなくて困ったことはありましたが、 それらはどちらかというとScala.jsの問題というよりScalaの問題だったので、社内のガチムチScalaエンジニアたちに助けてもらえました。

Scala.js自体で「困ったー」となったところはそこまで多くなかった印象です。

Q. ちゃんとメンテナンスされている?

Githubや公式サイトのNewsを見ていただければ活動が続いていることが見えると思います(2018/08時点)

github.com

www.scala-js.org

(たまたまNewsをみたら、今日ちょうどScala.jsの1.0.0-M5のリリース日でした)

利点と欠点

利点

実際に導入して以下のような良いことがありました

  • エンジニアの縦割り感が少し薄れた
    • ScalaエンジニアがPR投げてくれる、レビューしてくれる
      • 特に、frontend-backendはDOM API等のWebFrontend特有の知識がそこまでいらない層なので、参加しやすい
    • WebFrontendエンジニアがScalaちょっと書けるようになる
  • 楽しい

参考に、私のPRにScalaエンジニアがレビューしてくれてるやつを貼っておきます。

f:id:tan-yuki:20180813190621p:plain

欠点

今回frontendとbackendの二段構成にしましたが、やはり通常のJavaScriptのプロジェクトよりは構成を準備するオーバーヘッドは大きいです。 ある程度大きなプロジェクトでないと、このオーバーヘッドはペイしないのではないかと感じています。

今回のChatWork Liveのプロジェクトは前述したとおり、そこまで大きなプロジェクトでもなかったこともあり「少しやりすぎ感あるかな……」という印象はあります。 ただ、今後のプロジェクトにおいては、Scala.jsで構築するという選択肢が増えたことはよかったかなと感じています。

まとめ

そんなこんなでScala.jsを用いたChatWork Liveのリニューアルができました。 これからもScala.jsの知見がたまったら公開していこうと思います。

みなさんもScala.jsを使ってみてはいかがでしょうか?