Electronでシンプルな動画プレイヤーを作ってみた（技術編）

Electronでシンプルな動画プレイヤーを作ってみたので、その[機能記事](http://qiita.com/takeyuichi/items/82c155168b2dc7ae18a7)と技術記事を書こうと思います。本記事はその技術編です。

https://github.com/y-takey/shokushu

使用した主な技術要素などは以下です。

# [Electron](https://github.com/atom/electron)

説明するのも野暮だと思うので概要だけ。

> Electron（旧Atom-Shell）とは、Web開発者がHTML5とNode.jsでMac、Windows、Linuxのデスクトップアプリを作れるクロスプラットフォーム実行環境です。 Electronはオープンソースで無料で使える上に、MITライセンスであるため、商用利用も可能です。 開発元はGitHub社です。
[CodeZineより引用](https://codezine.jp/article/detail/8782)


# [React](https://github.com/facebook/react)

こちらも有名ですね。
やや古いですが、[この記事](http://qiita.com/koba04/items/4d13caf5ab4507974bf0)が簡潔にまとまっていて分かりやすかったです。

# [react-router](https://github.com/reactjs/react-router)

名前の通り、ルーティング周りのライブラリです。Railsでいう `link_to` メソッド等の機能ももっています。
URLに応じて対応するコンポーネントのレンダリング等を行ってくれます。

# [redux](https://github.com/reactjs/redux)

reduxは状態管理のためのフレームワークです。
[Redux入門【ダイジェスト版】10分で理解するReduxの基礎](http://qiita.com/kiita312/items/49a1f03445b19cf407b7)が分かりやすかったです。
実際に使ってみて、状態変化など分かりやすかったですし管理しやすかったです。(後述のボイラープレートによる部分も大きかったですが）
View,Action,Reducerそれぞれの役割が決まっているので、余計なことを考えず、その部分の実装に集中できましたし、ロジックも簡潔になりました。例えば、あるボタンを押した時、こっちのフラグが立っていたら〇〇とか複雑なことを考えなくてよかったです。
ただ自分の場合はActionとReducerの境界がはっきりしておらず、これはActionの仕事かなということもReducerでやっている感があります。

余談ですが、最近(2016年2月中旬頃)にreactjsに[移管された](https://github.com/reactjs/redux/issues/1392)ようです

# [electron-react-boilerplate](https://github.com/chentsulin/electron-react-boilerplate)

* 上記のElectron, React, React-router, redux 全てが入ったボイラープレートです。これを使うとスゴくお手軽です。
* 最近の流行りらしくgulpは使っておらずnpm scriptsでまかなっています。けど全然不便は感じません。
* ここらへんはよく分かっていないのですが、ソースコードを変更するといい感じにreloadしてくれます。webpack等のlive reloadとは違い、必要なモジュールだけreloadしてstateに応じて再描画してくれたり、actionの再実行をしてくれます。ただそのせいで、Reducerをべき等にしておかないといけません。（まぁこれはデメリットではなくメリットだと思います。）

* 他にもボイラープレート類はたくさんあるので、使いたい技術要素+「boilerplate」or「starter」などのキーワードをつけてググるとジャストフィットなものが見つかるかもしれません。

# [redux-devtools](https://github.com/gaearon/redux-devtools) & [atom-redux-devtools](https://github.com/zalmoxisus/atom-redux-devtools)

* boilerplateをそのまま使うとアプリの画面上にreduxのdevtoolsの領域が表示されるのですが、Electron自体のdevtoolもあるので、イヤだなーと思っていました。そうしたところ、Atomエディタにそれ用のタブを表示してくれる[atom package](https://github.com/zalmoxisus/atom-redux-devtools)を見つけたので採用しました。
* ちなみにGithubのREADMEには書かれていませんが、atomで `cmd + shift + d` とするとredux-devtoolsのタブが開きます。


# [lowdb](https://github.com/typicode/lowdb)

* lodashの関数でアクセスできる軽量DBです。簡易なものでよかったこと、もともとlodashに馴染みがあったこと、データをjsonで保存可能だったことから採用しました。
* 当初は想定していなかったjsonのexport,importも簡単に実現できて結果的によかったです。
* データ操作はサンプルに載っているように、`db('posts').chain().sortBy('views').take(5).value()` と`chain` を使ったのですが、最近「 [Why using `_.chain` is a mistake.](https://medium.com/making-internets/why-using-chain-is-a-mistake-9bc1f80d51ba#.y1sj16lm5)」という記事を読んで、なるほどと思いました。しかし書き直す気力はなく・・・

# [react-tags](https://github.com/prakhar1989/react-tags)

* タグ用のcomponentを探したところ、欲しい機能がだいたい揃っていたのがこれでした。
* ただし現在はあまり開発されておらず放置気味のようで、一抹の不安がありました。しかしコードを読んだ感じだといざとなれば自分でメンテできそうだったので採用しました。
* タグ入力時に何も入力してなくても候補を表示したかったのですが、そのままの使い方だと無理だった(最低1文字は手入力しないといけない)ので、ちょっと小細工しました。

# [marerial-ui](http://www.material-ui.com/#/)

* 有名なgoogleが提唱(?)しているマテリアルデザインのreact用UIライブラリです。
* 各種コンポーネントが手軽に使えて便利です。
* ただし生成されるDOMのstyle属性に直接書いてくるので、ちょっとしたカスタマイズはstyleオプションですることになります。適当なclass名を与えてCSSでやろうとしても「!import」ばかりになってしまう。。
* そのためコンポーネントのモジュール化がすすみ、感覚的にはWeb Componentsに近いと思いました。
* ちなみに、色は[カラーパレット](https://www.google.com/design/spec/style/color.html#color-color-palette)を見ながら、メインカラーとアクセントカラーを決めて、その他はメインカラーと同系色3,4色にしようと思っていたのですが、センスがなくて同系色5,6色くらい結局使ってしまいました・・・難しい・・・
* カラーパレットの色コードとライブラリの定数名(厳密には定数ではないですが)が同期しています。

たとえば、「Light Blueの900」の場合

```js
import Color from 'material-ui/lib/styles/colors'

const style = {
  color: Color.lightBlue900
}
```

# [React Infinite](https://github.com/seatgeek/react-infinite)

* リストが数百件になるとすごく重いので遅延レンダリングしてくれるcomponentを採用しました。
* 何も気にせず配列に数百件のデータを入れても、画面スクロールに応じて適量ずつレンダリングしてくれるので軽量です。
* ただし子要素はdivでラッピングされるので、リスト部分にtable,trタグを使うと実行時にレンダリングエラーになります。

# ライブプレビュー

ライブラリではないですが、ちょっと工夫したところを。
動画再生中にシークバーにマウスをホバーしたらそのシーンをプレビューできるようにしたかったのですが、最初はcanvasを使ってイメージを描画し、それをポップアップで表示させればいいと考えていました。が、描画するにはそのシーンを表示する必要があり、再生中動画はそのままにしたいから別にvideoタグ作って・・・と試行していたら、あれ？それならcanvas使う必要はなく、もう1つのvideoタグをポップアップすればよくない？と気付きました・・・「画像を表示したい＝canvasを使う」という思い込みがあったせいで、変な遠回りをしてしまいました。