はてブクライアントを作った

Rails, React/Redux構成で習作として何かWebアプリケーションを作ろうと思い、GW終わりから3日ぐらいでWebアプリケーションを作った。

f:id:tic40:20180510174108p:plain

こちら: https://tic40-emperor.herokuapp.com

*HerokuのFreeプランなので、サーバがsleep中だと表示にかなり時間がかかります

やりたいこと

  • Rails, React/Redux構成でWebアプリケーションを作る
  • できれば無料で

アプリケーション内容

特にアイデアが浮かばなかったので、普段よく使ってるサービスで何か作れないかなと思い、はてなブックマークの閲覧用クライアントを作ることにした。

  • はてなが提供しているAPI*1RSSからエントリー情報を取得する
  • はてなブックマークのホットエントリー一覧表示
  • エントリーの詳細情報(ブクマ数、コメント数、投稿日など)の表示
  • エントリーのコメント表示

技術構成

技術構成は以下

  • インフラ: Heroku(Free Dyno plan)
  • DB: Postge
  • キャッシュサーバ: Redis
  • CI/CD: CircleCI
  • 開発環境: Docker
  • Back-end FW: Rails v5.2.0, Node.js v9.5.0
  • Front-end FW: React v16 / Redux
  • CSS FW: Bulma

開発環境構築

Dockerで構築した

https://github.com/tic40/emperor/blob/master/Dockerfile https://github.com/tic40/emperor/blob/master/docker-compose.yml

DB設計

ログインもユーザ管理もしないので、ぱぱっと書いておわり

f:id:tic40:20180510180457j:plain

  • feeds: rssフィード情報を保持する
  • entries: エントリー情報を保持する
  • comments: エントリーに紐づくコメントを保持する

API設計

ReactからAPI経由でデータを取得する必要があるため、APIを設計する。

基本的にREST準拠で、レスポンスはjsonで返却する。

  • GET /api/v1/entries
    • エントリー情報全取得
  • GET /api/v1/entries/:feed_id
    • エントリー情報をfeed_id指定で取得

クローリング設計

はてブRSS*2から最新のホットエントリ一覧を取ってくる。 例えば総合カテゴリなら以下のURIから取得できる。

RSSのフィードはこちらから定期的に取りに行く必要があるので、スケジューラーでクローリングタスクを回すことにした。 Herokuアドオンのスケジューラー(無料)を使い、1時間おきに以下のクローリングタスクを走らせている。

https://github.com/tic40/emperor/blob/master/lib/tasks/task_crawl.rake

エントリー詳細情報の取得

RSSからホッテントリ一覧は取得できるが、エントリーに対するコメントなどの詳細情報は取得できない。 はてなが提供している はてなブックマークエントリー情報取得API*3 から取得することにした。

デプロイ

GitHubのmasterブランチ更新時に自動デプロイが走るようにCircleCIのデプロイレシピを記述した。

https://github.com/tic40/emperor/blob/master/.circleci/config.yml

実装

  • RailsAPIモード、かつv5.1から追加されたwebpackerオプションを指定して作成した
Rails new . --webpack=react --api
  • APIのレスポンスはHerokuのRedisアドオン(無料)を使い、キャッシュすることで高速した
  • フロントエンドの構成はReduxを使うため、以下のような構造にした。
# directories
app/javascript/packs/
   |-actions
   |-components
   |-containers
   |-reducers
   |-utils

感想とか

  • はてぶのAPIは user-agent ヘッダーをつけてリクエストする必要がある
  • Heroku無料プランだとDBレコードが10000までという制限がある。エントリーに対するコメントもDBにインサートしているため、あっという間に10000行を越えてしまった。特にデータを溜める意味はなかったので、DBにデータをためないようにRSS更新の際にレコード削除して直近のRSSに含まれているエントリー情報だけDBに保持することにした。
  • 1時間に一度しかクローリングしてないので、リアルタイム性は全然ない。
  • Herokuは楽
  • やっぱり個人で開発するならReactよりVueの方がいいかな。

GitHub

ソースはこちら

github.com