Upgrade to Pro — share decks privately, control downloads, hide ads and more …

導入して1年経ったReact周辺の 技術スタックを反省します | React反省会@Wantedly

導入して1年経ったReact周辺の 技術スタックを反省します | React反省会@Wantedly

React反省会@Wantedly 2017/05/10

20451aa93aace2f5279f5ea2e7a9c89d?s=128

Kento Moriwaki

May 10, 2017
Tweet

Transcript

  1. React反省会@Wantedly 導入して1年経ったReact周辺の 技術スタックを反省します Kento Moriwaki / 森脇健斗

  2. シゴトでココロオドル シゴトでココロオドル Reactを導入してから1年3ヶ月 経ちました 2

  3. シゴトでココロオドル • 導入方法 – 何を考えて、それはうまくいったか • 技術スタックの選択 – 導入時に考えたこと –

    反省点 – 改善アイデア • 話さないこと – React自体と他のframeworkとの比較 話したいこと 3
  4. シゴトでココロオドル • Kento Moriwaki • Wantedlyのエンジニア • 新卒入社して3年目 • 主にRailsとReact

    • Feed team & International team 自己紹介 4
  5. シゴトでココロオドル • jquery-ujs • Backbone • Angular 1 • React

    – 今ここ – 2016/02から1年3ヶ月 Wantedlyのフロントの歴史 5
  6. シゴトでココロオドル • 一気に全体に導入された • 詳しい人は一人だけ – コードレビューもほとんどできない – あまり良くないコードが堂々としている •

    みんな書きたがらない – 学習コストが高い – 勉強する余裕がない – とりあえずjQueryでなんとかすればいいか まずはAngular 1を反省 6
  7. シゴトでココロオドル • 書く人を増やすことに尽力した – 社内勉強会を何回も開催した • みんな興味はあるのでちゃんと聞いてくれた – Reactいいよ、と呟く •

    一部から導入した – 独立した機能から導入した – 新機能やリニューアル時に少しずつ増やしていった • デザイナーに認めてもらう – 前回Reactで作ったのが良かったから、次もあのクオリティに したい – React前提でデザインが進められる React導入時に注意したこと 7
  8. シゴトでココロオドル • React書く人増えてる – 自分のチームは全員書く – ほぼ全てのチームで導入されている • 10機能で使用されている •

    Component数は約300 その結果 8 よかった!
  9. シゴトでココロオドル シゴトでココロオドル いい話はここらへんにしておいて 9

  10. シゴトでココロオドル • React入れるには、他に色々判断しないといけない – 言語は? – どうやってビルドする? – Flux? –

    Styleは? – ディレクトリ構成は? – テストは? • 導入当時の選択を振り返って、反省したい React周辺の技術スタック 10
  11. シゴトでココロオドル • Tool – webpack, Babel, ESLint • Library –

    Redux, Redux-thunk, Immutable.js – CSSModules, react-css-modules • Other – flux, E2E test 今の主な技術stack 11
  12. シゴトでココロオドル Tools 12

  13. シゴトでココロオドル • Railsからは切り離し、webpackを使っている – webpack-dev-server すごく便利 • 完全なSPAではない • 独立した機能から使い出して、独立したアプリケーション

    がいっぱいできた – Entryファイルが機能ごとに分かれている • いざ全体にReactを入れていこうと思ったら、結構困った (困っている) webpack 13
  14. シゴトでココロオドル webpack 14 • 各機能が独立しているので、一 緒に読み込めない • リンク一つで遷移できるはずな のに、ページのフルリロードが必 要

    manage_posts.js analytics.js tickets.js messages.js
  15. シゴトでココロオドル • こういうファイルが何個もある – それぞれがstoreを作って、routingしてる • まとめるのはかなり大変 webpack 15 const

    store = configureStore(); const history = syncHistoryWithStore(browserHistory, store); ReactDOM.render( <Provider store={store}> <Router history={history}> <Route path='/enterprise/analytics' component={AnalyticsContainer} > <IndexRoute component={DashboardContainer} /> <Route path='company' component={CompanyContainer} /> </Route> </Router> </Provider>, document.querySelector('[react-component=EnterpriseAnalyticsContainer]'), );
  16. シゴトでココロオドル • 反省: アプリケーションは一つで、lazy loadで必要なも のだけ呼ぶようにする • webpackのdynamic importでできる –

    ComponentやActionだけじゃなく、reducerもreplaceで きる • Storeやroutingの設定は一つになるように • 全体は一つのアプリケーションで、必要なページで追加の コードが読まれるように webpack 16
  17. シゴトでココロオドル • もともと入れてなかった – Ruby側で使っていなかったから • すごいペースでコードが汚くなっていく – 使ってないのにimport –

    中途半端なpropTypes – `==` vs `===` – 人間の目ではレビューしきれない • 途中から導入することに • 詳しくはこちらに – 全力で大きくなるReactのコードをスタイルガイドに沿って見直したら、大変勉強に なりました | Wantedly Engineer Blog ESLint 17
  18. シゴトでココロオドル • 反省: 初めから入れて、徹底しよう • JSのコードは汚くなるもの • エディタでチェックするようにメンバーで共通する • レビューでは気づけないので、CIに入れてもいいかも

    • 厳しめに入れて、後から緩くすればいい ESLint 18
  19. シゴトでココロオドル Library 19

  20. シゴトでココロオドル • Immutable便利 – Immutable.Recordでビジネスロジックを持ったオブジェ クトを作れる – OrderedSetなどのデータ構造もよく使う • どこはImmutableで、どこはPlainなのか

    – ReducerごとのstateはPlain – EntityをImmutableでつくる – が、徹底して統一するのは難しい Immutable.js 20
  21. シゴトでココロオドル • このオブジェクトは、Immutable? • この配列はArray or Immutable.List ? • propTypesも適当になってくる

    – anyがいっぱい • どちらかに統一するというよりは、型が分か れば解決できる問題 – TypeScriptとかなら解決できる Immutable.js 21
  22. シゴトでココロオドル • 状態管理を行うcomponent – 主にReduxとconnectするcomponent • どこからContainerで、どこからComponentにするか – ページ単位? –

    Routing単位? – 実はどこでもいい Container(Redux) 22
  23. シゴトでココロオドル • Containerは一番外側のcomponent、みたいに思って いたおかげで、propsの受け渡しが多すぎるひどいコード が増えた • すごく雑なpropTypesや、全部受け取るconnectの出 来上がり Container 23

    export default connect( state => ({ analytics: state.analytics, }), dispatch => bindActionCreators({ ...actions }), )(AnalyticsContainer);
  24. シゴトでココロオドル • もっと細かくContainerを分けるべき – 必要ないstateも受けていると、パフォーマンスが 下がる – 受け渡すだけのprosは、可読性も下がるし、書く のもかなり面倒さい •

    ディレクトリ構成も一因に – Componentから遠いので、行き来するが面倒 – `import from ‘../../../containers/’;` Container 24
  25. シゴトでココロオドル Language 25

  26. シゴトでココロオドル • ES2015をbabelでトランスパイルしている • Stage-3まで使える – Candidateなので、大きく変わる可能性は小さい • それ以下は要相談 –

    `static propTypes =` などは使っている – simpleで変わる心配少ない & 変わっても簡単に直せ る & 可読性がかなり上がる – TypeScriptでもかけるし。。 ES2015 26
  27. シゴトでココロオドル • 型は必要だった? – Railsを書いている人が大部分なので、ハードル が高いと思った • CoffeeScriptからの差が大きい – 今はgolangとか書く人も増えてるし、型の良さも

    共通認識である(と思う) – TypeScriptのIntelliSenseがいい ES2015 27
  28. シゴトでココロオドル • 反省: TypeScriptにしても良かった – propTypesも標準じゃなくなるし – Googleでも標準言語になってるし – VS

    Codeで生産性高いし • 途中からTypeScriptにするのは骨が折れ そうだから、初めからTSにできるならした方 がいい • Flowでも可 ES2015 28
  29. シゴトでココロオドル Test 29

  30. シゴトでココロオドル • 現:JSの単体テストはなく、Railsも含めたE2Eテストで担 保している • Wantedlyのwebエンジニアは、フロントもサーバーも一 人で書く場合が多い – バーっと動くものをつくって、重要なところをE2Eで担保 していくスタイルがあっていた

    • Angular時代も単体テストを書く環境はあったが、ほとん ど書かれることはなかった テスト 30
  31. シゴトでココロオドル • 反省: テストはかけた方がいい • 全てE2Eテストを書くのは大変 • 各Component書く必要はなさそう • ActionCreatorや、ビジネスロジックはテス

    トが書かれるべき <- 当たり前 • 環境整えるのが大変なので、誰か助けてくだ さい テスト 31
  32. シゴトでココロオドル Directory Structure 32

  33. シゴトでココロオドル • react/ – components/ • {fooapp, barapp}/ – containers/

    • {fooapp, barapp} – reducers/ • {fooapp, barapp} – actions/ • {fooapp, barapp} – lib/immutable/ ディレクトリ構成 33 • 外側は役割ごとに分けられて いる • その中は、機能ごとに同じよう に分けている • 実際はもうちょっと汚い • 初めはflatだった • 一つの機能が離れたところに
  34. シゴトでココロオドル • StateとUIを分けるべき – アプリケーションの状態とUIのReactとは切り離す – ComponentsとContainerはディレクトリで分けなく ても良さそう • 関心ごとにまとめるべき

    – 一つの機能に関するコードを近くに集めることで、 データの流れが追いやすくなる • 参考 – Automattic/wp-calypso ディレクトリ構成 34
  35. シゴトでココロオドル • components/ – {fooapp, barapp}/ • Baz.jsx • BazContainer.js

    • state/ – {fooapp, barapp}/ • action.js • reducer.js • selector.js • models/ ディレクトリ構成[理想] 35
  36. シゴトでココロオドル Others 36

  37. シゴトでココロオドル • CSSModulesを使っていた – CSSが分かれていて、デザイナーでも触りやすい – Rails側でscssを使っているので、変数の共有な どのために統一した • react-css-modules

    – className={style.tabel} – styleName=’table’ – 書く量が減って、いいかなと思った CSS 37
  38. シゴトでココロオドル • react-css-modulesのパフォーマンス – 実行時の解決なので、コストがかかる • babel-plugin-react-css-modules – BabelのCompile時に解決してくれるのでパフォー マンスがいい

    – 何が起きてるかわかりにくいbabelのpluginは入れ たくない • 学習コストが上がる • なんでもできちゃう CSS 38
  39. シゴトでココロオドル • シンプルにCSSModulesだけで良かった • className={s.table}って書くだけで、大し て面倒ではない – 直感的に理解できる – undefinedチェックとか実装時はうざいだけ

    <= 設 定の問題 – camelCaseのスタイルでもいいじゃん CSS 39
  40. シゴトでココロオドル • State treeからデータを取ってくる関数 – 離れた場所のデータを組みわせて使いたい場面 とかに便利 – redux/reselect を使うとメモ化なども行なってくれ、

    パフォーマンスにも優しい • 初めは、render内で毎回計算したり、state に保存したりしていた Selector 40
  41. シゴトでココロオドル • state treeの構造をどうするべきか – APIのデータをそのままstateに入れると、nestが 深くなる – 深いデータが更新されると、上側も全て更新され る

    – パフォーマンス的にもよろしくない – データの一貫性を保つのが難しい • Reducerのコードが複雑になる Normalize 41
  42. シゴトでココロオドル • 各entityごとにnestを均してから保存する – IDをkey, entityをvalueにしたMapに保存 – 元あった場所にはIDを入れておく – propsはIDを渡して、connectでentityを取ってくる

    • 利点 – 関係ないデータが変更されても、updateが少なく なる – Reducerの処理がシンプルになる • IDからデータを探して更新するだけ Normalize 42
  43. シゴトでココロオドル • Reduxのmiddleware – Actionのdispatchに割り込んで、色々できる • 非同期処理を扱うために、redux-thunkだ け入れた – Simpleでとにかく学習コストが低い

    • Loggingなどの副作用や、共有化された APIコールなどで、適宜作っている • こういうところに単体テストがないの良くない middleware 43
  44. シゴトでココロオドル まとめ 44

  45. シゴトでココロオドル • React導入一年経って、うまくいっていると胸 を張って言える • チームの状況を見てスタックを選択しよう – Wantedlyは一人がサーバーとフロントを両方書く 体制 •

    大きな失敗はないけど、もっとよくできたと反 省は絶えない • これから導入する人の参考になれば嬉しい まとめ 45
  46. シゴトでココロオドル We are hiring! 46 https://www.wantedly.com/projects/59809