ランサーズ等のサービスを開発・運用する中で得た知識やノウハウを紹介しています。

thumbnail

Labels:  JavaScript 投稿者:mori-dev

ランサーズ流 React.js/redux アプリ開発入門

はじめまして、森(@mori-dev) と申します。React.js/redux, Rails, Node を使ったアプリの開発を行っています。

このエントリーでは、ランサーズでの React.js/redux プロジェクトの設計/実装などの雰囲気がわかるような概要を書きます。

じっさいのプロジェクトのコードはそれなりのサイズですので、lancers-redux-sample-app という形で基本的な部分を取り出しました。GitHub で公開しています。

コミットはすべて私になっていますが、チームの成果からの抽出です。フロント側の開発メンバーは私の他に @numanomanu さんと @takepo さんです。
ではコミットを追ってゆきます。パッケージ管理では yarn を使っています。

yarn 導入以前は、npm shrinkwrap でした。その頃は ci-npm-update も使っていました。現在はパッケージのアップデートは、ときどき yarn-update で行っています。CI 連携させたいですね。
CircleCI の yarn の設定はこのようにしています。

もっと高速にできそうな資料 `amakanでyarnを使うようにした` はみつけたのですが、まだ試していません。CIの遅さは Rails アプリ側の方がひどいので、対応の優先度は低いです。
ディレクトリレイアウトはこうです。普通です。

containers と components の使い分けは、いくつか記事をみかけましたが Container Components が参考になります。

プロジェクト単位での npm の設定を、プロジェクトディレクトリ直下に .npmrc を配置して行います。

npmrc の使い方は `project毎のnpmコマンドをいい感じにするnpmrc & config達` が参考になります。今回設定したキャレット(^)とチルダ(~)の違いは `package.json のチルダ(~) とキャレット(^)` が参考になります。
以下の一連のコミットで、開発ツール群のインストールと設定を行いました。

フロント側で採用しているおもなライブラリは以下です。

  • React.js
  • redux
  • webpack
  • babel
  • flowtype
  • eslint
  • cordova

あとは Immutable.js があるといいですね。

次は eslint の設定です。現在のメンバーは、この値に強いこだわりがあるわけではありませんが、プロジェクト内で書き方が統一されているのは重要です。eslint は、プログラムファイルを目を細めてみたときの図形としての美しさからセキュリティ上の指摘まで、ずいぶんいろいろみつけてくれるので、機会があれば真剣に検討するとよいのかもしれません。既存実装をすべて修正していただけるなら、.eslintrc.yaml の値を変更するプルリクエストは、おそらく通します。

以下のコミットでは、webpack があれこれした結果をメモリではなくファイルに書き出すようにしています。これは webpack-dev-server のビルド結果に対して cordova build ios を自動でできると開発効率があがるのだが… と思い導入したのですが、まだうまくいっていません。インメモリファイルシステムとかされるとアイディアがわかないので、ハッカビリティだけ提供して放置しています。そのうち消すかもしれません。

以下のコミットで、wewbpack の設定ファイルと本番環境用と開発環境用に分離しています。こちらはそのうち必要になるだろうから、新卒の @takepo さんにお願いするとわりとサクッと作ってくれました。成果は `webpackの設定ファイルを環境ごとに分けるには` にまとまっています。なお、このエントリでお手本にしているランサーズのアプリは、まだ本番リリースを行っていません。webpack.config.production.js の内容はそのうち変わるはずです。

/home という URL 付きで、HOME コンテナ関連をつくりました。

/another という URL 付きで、もう1画面つくりました。

以下の一連のコミットで、Qiita の ユーザーリスト API コールを行い、/another の画面で、その結果を表示するようにしました。

次のような特徴があります。どれも定番化していると思います。

  • API コールのアクションを、開始アクション、成功アクション、失敗アクションにわける
  • redux-saga を用いる

API仕様はアンダースコア区切り、JS側はローワーキャメルケース、という状況がよくあります。今回のアプリでは次のようなミドルウェアで対応しています。ミドルウェアでのアクションの選別が、`_START` とった命名規則に依存しているところが若干気に入らないのですが、まぁいいやと思っています。

navigator.onLine でオフライン通知を行うようにしました。Rails アプリ開発になぞらえると、ミドルウェアはアクションに対する before action 的な使い方ができます。

ログインチェックの仕組みも書いてみました。じっさいのログインチェック自体は割愛します。ここでは HOC(Higher Order Components) を使っています。この場合は、HOC はコンポーネントのマウントに対する before action 的な使い方をしています。

HOC で何ができるのかを知りたければ、`ReactのHigher Order Components詳解 : 実装の2つのパターンと、親Componentとの比較` という記事が参考になります。
テスト、型定義、CSS 関連は省略しましたが、ここまでで、私達の React.js/redux アプリでは、どのようなライブラリを採用して、どのような実装を行っているのかの概略を説明しました。すべてはお見せできませんが、とくに尖ったことはしていないし、これといってひどい設計/実装にもなっていません。アプリの設計方針/採用技術の取捨選択の指針として、「次の普通になりそうな新しい技術を、ある程度情報が出揃った段階で積極的に導入したい」と考えています。

私の把握している、現在の課題を列挙しておきます。

  1. saga のテストがない
  2. ジェネレータの型がない
  3. まだ私達は型を使いこなしていないのではないかと不安になることがある
  4. モデリングがてきとう
  5. 忙しくなってきてリファクタの時間が取りにくい

1 は何かとのトレードオフです。 2 は過去に挑戦して難しくてよくわかりませんでした。私にとっては、わりと優先度の低い課題です。3,4 が最大の関心事です。これらは関連しているはずです。プロジェクトの初期は、何かしらの構造をもつデータの型を types/models.js に置いていました。最近は APIコールや WebSokct 通信の payload を types/payload/*.js に必ず書くようにしています。API コールや WebSokct 通信で何が期待するデータの受け渡しなのかが コードからわかって有益です。アクションクリエータの引数のフォーマットも統一されます。もっと大きな改善になりそうなのは `React使い必見! Immutable.jsでReactはもっと良くなる`で紹介されているモデリングだと思います。近いうちに導入したいです。私の観測範囲では、「ビジネスロジックをミドルウェアに追い出す」から「Immutable.Record() でクラス化する」といった発展を感じました。複数アクションに共通する処理なら、ミドルウェアから Immutable.Record() なクラスを使えばよいし、将来的な拡張もふくめて一つのアクションにしか適用しない処理なら、わざわざミドルウェアをつくらず、かわりに Immutable.Record() なクラスを作って、アクションでその Immutable.Record() なクラスを使えばよさそうです。

プロジェクトが進み、APIサーバー側で別チームをつくると、フロント側の開発リソース不足が目立ってきました。ここまでの説明を読みこなせるようであれば、ぜひいっしょに仕事がしたいです。今のところ、フロントエンドエンジニアとしてキャリアを積むのに、魅力的な環境は維持できています。現場からは以上です。

ランサーズではサービスを成長させてくれるエンジニア、デザイナーを募集しています!
ご興味がある方は、以下URLよりご応募ください。


【中途採用】
サービスリードエンジニア
テックリード(アーキテクト)
フロントエンドエンジニア
サーバーサイドエンジニア
業務エンジニア(社内システム基盤・基幹システム)

【インターン・学生バイト】
19新卒対象サマーインターン
エンジニアインターン

その他採用情報

関連記事

ES6 + React.js + Redux で作るチャットシステム

アプリケーションエンジニアのyutakaです。 先日ランサーズのメッセージ機能をリニューアルしました。 ランサーズのメッセージ機能はリアルタイムのチャット形式で他のユーザーさんとコミュニケーションがとれる機能となっています。 リニューアルに伴って、フロントエン …

thumbnail
コールバックスタイルの外部ライブラリなどの関数を redux-saga で使うには

森です。本日の課題とその対処です。 課題 外部ライブラリの関数が、コールバックスタイルのため、redux-saga の自前実装部分との実装の統一感がない。たとえば、navigator.geolocation.getCurrentPosition で現在地を取得 …

thumbnail
React × Redux で action 発行時に確認ダイアログを挟む middleware の実装例

pookチームのtakepoです。 今回は、React × Redux でstateを変更する時にダイアログ等で確認表示を挟みたいときの良い方法をご紹介します。 その場合の例として、「ユーザーの情報を更新するとき、更新しても良いかを一度確認するダイアログ表示す …