SPAをつくるために使ったものたち

# つくっているSPA
[Sakepedia](https://www.sakepedia.io/)という日本酒の情報検索・登録・共有サイトです。
OSSのSPA(Single Page Application)で、コンセプトとかソースはGitHubをみてください。

https://github.com/itagakishintaro/Sakepedia

ここでは、使っているものとその用途を使ってみた感想とともに簡単に紹介しようと思います。

## SPAとは
SPAとはSingle Page Applicationのことで、私は2014年のJolt Awardsをとった書籍「[シングルページWebアプリケーション](http://amzn.asia/7M9OjCb)」で知りました。
この本を読んで最初につくったのは、[99colors](http://s-ita.net/99colors/)というカラーコードを共有するWebアプリ。
SPA用のフレームワークとかはなかった（ように思う）ので、特にフレームワークは使っていませんが、[Sakepedia](https://sakepedia.herokuapp.com/)では、フレームワークを使っています。

## アプリの構成概要
サーバーサイドはRESTのWeb APIでデータの操作を提供するだけです。
Node.js, Express, MongoDBを使っています。

クライアントサイドは、React/Reduxを使っていて、UIはmaterial-uiを使っています。

その他、Google Vision APIで画像から文字おこしをしたり、Google Sheets APIを使ってGoogle Spread SheetsをDBのように使っています。
あと、まだ途中ですが、Googleが提唱しているProgressive Web Appsにしたいと思っています。

# 使っているものたち
## インフラ
### [GitHub](https://github.com/)
いわずもがなのGitのクラウドサービス。
もはや、これがなくなると本当に困ってしまう。
HTML5だけでつくったものは、[GitHub Pages](https://pages.github.com/)で公開していますが、今回はサーバーサイドがあるので次に紹介するHerokuで公開しています。

### [Heroku](https://www.heroku.com)
SalesForceに買収された最も有名なPaaSの1つです。
採用理由は、単純に、無料で使えて昔から使っていたからです。
個人的な注意点としては、次の点です。

* [無料枠](https://www.heroku.com/pricing)
すべてのアプリ合計で1000時間/月まで無料。
私の場合は、今のところ1つのアプリだけを公開しているので無料枠で十分です。

* アクセスしないと寝る
一定時間アクセスしないと、サーバーが寝てしまい、寝てしまった後の最初のアクセスが遅くなるので困ります。
しかし、常に起こしておくための方法があって、ググればすぐにできるので困りません。

## サーバーサイド
サーバーサイドはRESTのWeb APIだけなので薄いです。
[Node.js+Express+MongoDBでREST APIをつくる](http://qiita.com/itagakishintaro/items/a1519998a91061cbfb1e)をみていただければ、初心者でもつくれると思います。

### [Node.js](https://nodejs.org)
私の場合、Node.js(+Express), PHP(CakePHP), Ruby(on Rails)が選択肢としてあったのですが、今回はRESTのWeb APIだけなので、サーバーサイドは薄いし、クライアントがJavaScriptなので、一番楽だろうという判断でNode.jsにしました。

### [Express](http://expressjs.com/)
正直、Node.jsをはじめたときにセットで入れていたので、どこからがExpressなのかという感じです。
express-generatorを使ってベースを作れるのが便利。

### [MongoDB](http://www.mongodb.org/)
MongoDBのよいところはスキーマレスなところ。
仕様なんてなく、思いつきで開発するため、かっちりとしたDBだと色々と面倒なので、自由度が高いMongoDBにしました。
そういう理由なので、Mongooseは使っていません。
使ってみた感想としては、SQLだと簡単なことが調べないとできなかったり、[MongoDB Node.JS Driver](https://mongodb.github.io/node-mongodb-native/)がMongoDBでできることが全てできるわけじゃなかったり（たぶん）するのが困りました。
仕様変更は楽だけど、ちょっと複雑なクエリーを使いたいときは、ちょっと大変という感じです。

## クライアントサイド
クライアントサイドのフレームワークは色々でていますが、コンポーネント志向という点では共通しているので、どれかを学ぶと他も使えるようになるという感じがしました。
今回はReactを使いましたが、Angular, Polymer, Vue.js, Riot.jsのどれかを学ぶと、他も入りやすくなるはずです。
どれもさわってみた程度ですが、個人的には次の印象です。

* React: Facebookが開発しているので安心できるし、思想もしっかりしている。
* Angular: Googleなので安心。1系は思想が新しくないので、古いエンジニアにはかえってなじみやすい。2系はTypeScriptが基本になっているので、個人的に敬遠した（ES6がいい派）。
* Vue.js: ライトウェイトでよい。でも、使いこんでいって、込み入ったことをしたいときに大丈夫かちょっと心配（杞憂か？）。
* Riot.js: 個人的にはこれが一番バランスがいいと思う。ReactはCSSコーダーと分業しにくい問題が解決できるので、こっちにしておけばよかったかなぁと思っている。

### [React](https://facebook.github.io/react/)
Angular 1系を使ったことがあったので、最初はAngular 1系か、がんばって2系にするか悩んでいたのですが、ちょうどそのとき、「これからはReactで決まり！」的な記事をいろいろ見てしまったのでReactにしました。
使ってみた感想は次のとおりです。

* webpackとかの開発環境準備がめんどくさい
* JSXがはじめは気持ち悪い
* ライフサイクルとVirtual DOMをちゃんと理解できてない（あれ、と思うことがたまにある）

開発環境は[react starter kit](https://www.reactstarterkit.com/)がでたりしているので、JSXが大丈夫なら、とてもよいと思います。

### [Redux](https://github.com/reactjs/redux)
正直、Reactとセット的な感覚で使ってしまいました。
今思うと、ReduxなしでReactだけでもできたのかな？と思ったりもします。
使ってみた感想は次のとおりです。

* ComponentとContainerの違いがピンとこなかった
* コンポーネント間でのデータの受け渡しでとまどった

### [material-ui](http://www.material-ui.com/)
Reactで使えるCSSフレームワークを探して、よさそうだったので採用しました。
使ってみた感想は、次のとおり。

* CSS in JSではなく、CSS Modulesベースにしてほしかった
* スマホ前提的な感じだけど、PCでも使うので、レスポンシブにしてほしかった

CSS in JSは慣れると気にならないのですが、なんとなく罪悪感があります。。。

## サービス、API
### [Google Vision API](https://cloud.google.com/vision/?hl=ja&utm_source=google&utm_medium=cpc&utm_campaign=2015-q1-cloud-japac-jp-vision-bkws-freetrial-jap&utm_term=%2Bgoogle%20%2Bvision%20%2Bapi&gclid=Cj0KEQiAsf_BBRDMpoOHw4aSq4QBEiQAPm7DL9ZL6ehV-rbrVKn8TmzPoDCwPE4Qq9i67Fb3il5FTj8aAg7y8P8HAQ)
HTML5カンファレンスで知ったので、使ってみました。
用途は日本酒のラベルから文字おこしをするというもの。
日本酒のラベルに書いてある説明を入力するのは結構手間なので、使ってみると結構便利でした。
1000回/月まで無料なので、本当にありがたい。

### [Google Sheets API](https://developers.google.com/sheets/?hl=ja)
ITに詳しくない人も含めて、みんなで編集したいし、みんなに使ってほしいデータ。
データの量はそれほど多くないけど、画面のUIで操作するのは大変。
そんなときはやっぱりスプレッドシートですよね。
Google Docsには「提案->承認」の機能があるのですが、Spread Sheetにはないので、次のようにして手動で「提案->承認」を実現しています。

* みんなが編集できるように公開したブックは、編集があるとメールで通知するようにする
* アプリで使うものは、公開用とは別にプライベートにして、みんなの編集が変なものでなければ手動で反映する。

あと、V4になってAPIを使うのが面倒になった気がしました。
今回は、APIは単純なgetしか使わないのに、OAuth認証が面倒で、以外に時間がかかりました。
V3のURLたたくだけのAPIも使えるのですが、そのうち使えなくなったら嫌なのでV4のAPIを使いました。

## その他
### [Progressive Web Apps](https://developers.google.com/web/fundamentals/getting-started/codelabs/your-first-pwapp/?hl=ja)
Googleが提唱しているHTML5のService Workerを使ったネイティブアプリのようにWebアプリを使えるようにする考え方です。
HTML5カンファレンスで知りました。
Chromeしか完全には対応していないので、まだまだですが、これらが普通になるとかなりいいと思います。

実際にやってみたのは次。

* ホームに追加
* Cache（オフラインで使えるように）

ホームに追加は簡単なのでおすすめです。
Cacheは実装はそれほど難しくないですが、どの[戦略](https://github.com/kuu/the-offline-cookbook-ja/blob/master/ja.md)にするべきか結構悩みます。
あと、テストもしにくいし、対応していないブラウザが多いので、正直、今時点ではあまり使えないという印象。

これから取り入れたいと思っているのは次。

* Push通知

### [PhoneGap](http://phonegap.com/)
今は使ってませんが、前に使って便利だったので、そのうち使ってモバイルアプリにしてもいいかなと思っています。

[PhoneGap Builderを使ってHTMLでモバイルアプリを作る](http://qiita.com/itagakishintaro/items/60dc2138a6b64e4dda89)