マスコットアプリ文化祭でこのはちゃんとあんずちゃんのアプリを作った話
この記事は、ConoHa Advent Calender 2016の16日目の記事です。
技術的な内容メインじゃないのでQiitaじゃなくてこっちに書きます。 ConoHaにはCoreOSをインストールしていて、DockerでWebアプリをデプロイしてたりします。
マスコットアプリ文化祭とは
企業や団体のイメージキャラクターを使った作品のコンテストです。 作品はアプリに限らず、イラストや動画でもOKな感じになっています。
mascot-apps-contest.azurewebsites.net
このマスコットアプリ文化祭で2014年と2016年はConoHaがスポンサーをしていたため、このはちゃんやあんずちゃんのアプリを作りました。
もちろんどちらのアプリもConoHaで動かしています!
それにしてもいつもこのはちゃん負けてますね
みくもファンクラブ
これは2014年に作った作品で、ConoHa byGMO賞に選ばれました! このアプリは「このはちゃん大好き!」と「あんずちゃん大好き!」と書かれたボタンが設置されており、 これを押すとカウントが増えてキラキラ光るようになってます。 それと同時に、このサイトを見ている他の人の画面でもカウントが増えてキラキラ光ります。 このはちゃん派とあんずちゃん派でクリック合戦が始まり、両者とも1000万を超えてしまいました。
実装はNode.jsを使っています。 当時自分が使ってみたかったという理由だけでSailsを使っており、 またデータベースも特に何も考えずにmysqlを使っていたため、大量にクリックされたときの負荷がすごかったです。 やばいときはCPUフル稼働でした。
様子です pic.twitter.com/zuKk4PLoZO
— ABCanG(阿部) (@ABCanG1015) December 2, 2016
現在はSailsとmysqlをやめて、socket.ioとredisで動かしています。(みくもスタンプを作った後に作り直しました。) みくもファンクラブはDockerのnginx-proxy経由で動かしています。 以前はみくもファンクラブのコンテナだけがCPUを使いまくっていましたが、 改善後はnginx-proxyもCPUを多く使うようになったので、だいぶ高速化されました。 1秒あたり1000クリックがあってもわりと余裕で捌けるようになっています。
上の方から順に、みくもファンクラブ(User)、みくもファンクラブ(System)、nginx-proxy(System)、nginx-proxy(User) pic.twitter.com/ElA47SCwVp
— ABCanG(阿部) (@ABCanG1015) December 2, 2016
ソースコードを公開しているので気になる人はどうぞ。
みくもスタンプ
これが2016年に作った作品です。 このアプリは名前の通りみくもスタンプ(LINE版もあります)をお試しできるというものです。 みくもファンクラブみたいに大量クリックでスタンプ爆撃ができるようにと想定して作ってあります。 しかし、なんかみくもファンクラブの方が盛り上がっちゃって、あまり利用されてない感じがします。
お!既読が4ついたぞぅっ!https://t.co/NgZG5WIKSZ pic.twitter.com/KjVOmwJEWV
— 美雲このは (@MikumoConoHa) December 1, 2016
待って。負けてるじゃん。https://t.co/ESlzXqUQjR pic.twitter.com/Ru2wPlUcmZ
— 美雲このは (@MikumoConoHa) December 1, 2016
いいぞ!その調子!がんばれこのは!!https://t.co/ESlzXqUQjR pic.twitter.com/kmofoSfcgU
— 美雲このは (@MikumoConoHa) December 1, 2016
実装はみくもファンクラブと同様にNode.jsで作っています。 WebSocket周りの実装をする時はsocket.ioが便利というところが大きいですね。 こちらもソースコードを公開しているので気になる人はどうぞ。
詳しい実装とか
みくもファンクラブとみくもスタンプはほぼ同じような実装なので、みくもスタンプの実装について書いていきます。 みくもファンクラブは以下のライブラリとかで構成されてます。
- Node.js v7
- redis
- koa 2
- socket.io
- harp
- Vue.js
ざっくり説明すると、koaで書いたサーバにsocket.ioに繋いで、データはredisで管理しています。 htmlはharpであらかじめビルドしたものを配信しており、 フロントはVue.jsで書いています。
harpとkoa
まずharpについてですが、これはnode製の静的サイトジェネレータです。
cssじゃなくてsassとかで書きたかったのと、htmlの内容を開発環境と本番環境で変えたかったので使ってみました。 javascriptのminifyはしてくれなかったので、そこはしかたなくuglifyjsを直接使うことにしました。 glup書きたくないマンなので、npm scriptに仕込んで使っています。
{ "scripts": { "build": "harp compile client/src public && uglifyjs -c -o ./public/js/app.min.js ./public/js/app.js" } }
harpはコマンドでビルドしたり開発用のサーバを立てたりするだけでなく、 expressのmiddlewareとしても利用することができます。 今回はexpress用middlewareをkoa向けに変換してくれるkoa-connectを使用しました。 npmで提供されているバージョンは少し古く、koa 2で使用するためにはgithubのコードを使用する必要がありました。
koa周りのコードは以下のような感じになってます。 コード的には本番環境ではkoa-staticでファイルを静的配信するようになっていますが、 実際には静的ファイルはnginxが配信していて、koaの機能はあまり使ってません。 開発時にはharpをkoaで使うようにしています。 また、socket.ioはkoa経由で動くようにしています。
const app = new Koa(); if (process.env.NODE_ENV === 'production') { app.use(serve(path.resolve('./public'))); } else { console.log('development mode'); app.use(serve(path.resolve('./client/src'))); app.use(c2k(harp.mount(path.resolve('./client/src')))); // 開発時はharp経由で } const server = app.listen(process.env.PORT || 3000); const io = require('socket.io').listen(server);
Node.js v7とredis
Node.js v7からasync awaitが使えるようになった(フラグを指定する必要がありますが)ので、バンバン使ってみました。 感想としては、めちゃくちゃきれいにコードが書けて最高という感じでした。
const [stampsData, anzuCount, mikumoCount, conohaCount] = (await redis.multi() .lrange('stamps', 0, 49) .get('count:anzu') .get('count:mikumo') .get('count:conoha') .exec()).map((res) => res[1]);
このコードはアクセス時に現在のデータを取ってくる処理です。 redisへのアクセスはPromiseが使用できるioredisを使っています。 トランザクション処理もこのようにawaitと分割代入を使ってスッキリと書けました。
// 消えたスタンプの既読キーを削除 (await redis.hkeys('views')).reduce((pipeline, id) => { if (stampIds.includes(Number(id))) { return pipeline; } return pipeline.hdel('views', id); }, redis.pipeline()).exec();
このコードでは、redisから取得した配列に対してreduceメソッドを実行しています。
async awaitがないとここまできれいには書けないですね。
余談ですが、redis.pipeline()
はPromiseを返して、hdel
などのメソッドを実行してもPromiseを返してくれるので、
Array.prototype.reduceを使うとパイプラインを繋ぎやすくて非常にいいですね。
フロント側のコードとVue.js
この小規模なアプリでbabel使うのもなーということで、 フロント側のコードはES5で書きました。 そしてライブラリなどはcdnのものを使うようにしています。
今回ずっと気になっていたVue.jsを初めて使ってみました。 Vue.js 2系使いはじめて数日経った時に丁度2系向けの日本語ドキュメントが出て非常に助かりました。 Vue.js 2系からコンパイルするということもできるようになっていますが、 webpackとかもあまり入れたくないなーということで、今回は普通にhtml内に書くことにしました。
また、Bootstrap大好きマンなのでvue-strapを使用しています。 ただ、Vue.js 2系向けのは現在開発中でpreview版がgithubから使える状態になっているため、 今回はそれを使用しています。 正式公開されてcdnとかで配信されるようになったら修正しようかなと思ってます。
おわりに
アプリの紹介も少しだけで、なんだか何を言いたい記事なのかよくわからない感じになってしまいましたが、 とりあえずアプリで遊んでみてくださいってことで終わろうかと思います。
- 出版社/メーカー: ConoHa
- メディア: エレクトロニクス
- この商品を含むブログを見る