Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
導入して1年経ったReact周辺の 技術スタックを反省します | React反省会@Wantedly
Search
Kento Moriwaki
May 10, 2017
Programming
10
8.6k
導入して1年経ったReact周辺の 技術スタックを反省します | React反省会@Wantedly
React反省会@Wantedly 2017/05/10
Kento Moriwaki
May 10, 2017
Tweet
Share
More Decks by Kento Moriwaki
See All by Kento Moriwaki
わかった気になれる CRDT を使った共同編集
kentomoriwaki
8
4.2k
デザインシステムを導入してUIに秩序を取り戻す - React (Native)編 #rejectron2018
kentomoriwaki
16
3.6k
ReactでWebとNativeの共通UIライブラリを作ろう
kentomoriwaki
0
1.1k
BFFを導入しなかった理由
kentomoriwaki
4
13k
TypeScript in Wantedly
kentomoriwaki
2
720
5分でわかる React "Suspense"
kentomoriwaki
3
1.5k
Immutable.jsとReact @Wantedly ~入門編~
kentomoriwaki
8
74k
React速習会@Wantedly
kentomoriwaki
1
420
Other Decks in Programming
See All in Programming
Develop Faster With FrankenPHP
dunglas
2
3.2k
小田原でみんなで一句詠みたいな #phpcon_odawara
stefafafan
0
320
Qiita Bash
mercury_dev0517
1
190
Defying Front-End Inertia: Inertia.js on Rails
skryukov
0
460
エンジニア未経験が最短で戦力になるためのTips
gokana
0
260
スモールスタートで始めるためのLambda×モノリス
akihisaikeda
2
180
The Weight of Data: Rethinking Cloud-Native Systems for the Age of AI
hollycummins
0
270
MCP調べてみました! / Exploring MCP
uhzz
2
2.2k
AIコードエディタの基盤となるLLMのFlutter性能評価
alquist4121
0
200
AI Agents with JavaScript
slobodan
0
220
英語 × の私が、生成AIの力を借りて、OSSに初コントリビュートした話
personabb
0
180
Chrome Extension Techniques from Hell
moznion
1
160
Featured
See All Featured
The Illustrated Children's Guide to Kubernetes
chrisshort
48
49k
Done Done
chrislema
183
16k
Producing Creativity
orderedlist
PRO
344
40k
Fireside Chat
paigeccino
37
3.4k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
135
33k
YesSQL, Process and Tooling at Scale
rocio
172
14k
Java REST API Framework Comparison - PWX 2021
mraible
30
8.5k
Why Our Code Smells
bkeepers
PRO
336
57k
Docker and Python
trallard
44
3.3k
Facilitating Awesome Meetings
lara
54
6.3k
Build The Right Thing And Hit Your Dates
maggiecrowley
35
2.6k
Gamification - CAS2011
davidbonilla
81
5.2k
Transcript
React反省会@Wantedly 導入して1年経ったReact周辺の 技術スタックを反省します Kento Moriwaki / 森脇健斗
シゴトでココロオドル シゴトでココロオドル Reactを導入してから1年3ヶ月 経ちました 2
シゴトでココロオドル • 導入方法 – 何を考えて、それはうまくいったか • 技術スタックの選択 – 導入時に考えたこと –
反省点 – 改善アイデア • 話さないこと – React自体と他のframeworkとの比較 話したいこと 3
シゴトでココロオドル • Kento Moriwaki • Wantedlyのエンジニア • 新卒入社して3年目 • 主にRailsとReact
• Feed team & International team 自己紹介 4
シゴトでココロオドル • jquery-ujs • Backbone • Angular 1 • React
– 今ここ – 2016/02から1年3ヶ月 Wantedlyのフロントの歴史 5
シゴトでココロオドル • 一気に全体に導入された • 詳しい人は一人だけ – コードレビューもほとんどできない – あまり良くないコードが堂々としている •
みんな書きたがらない – 学習コストが高い – 勉強する余裕がない – とりあえずjQueryでなんとかすればいいか まずはAngular 1を反省 6
シゴトでココロオドル • 書く人を増やすことに尽力した – 社内勉強会を何回も開催した • みんな興味はあるのでちゃんと聞いてくれた – Reactいいよ、と呟く •
一部から導入した – 独立した機能から導入した – 新機能やリニューアル時に少しずつ増やしていった • デザイナーに認めてもらう – 前回Reactで作ったのが良かったから、次もあのクオリティに したい – React前提でデザインが進められる React導入時に注意したこと 7
シゴトでココロオドル • React書く人増えてる – 自分のチームは全員書く – ほぼ全てのチームで導入されている • 10機能で使用されている •
Component数は約300 その結果 8 よかった!
シゴトでココロオドル シゴトでココロオドル いい話はここらへんにしておいて 9
シゴトでココロオドル • React入れるには、他に色々判断しないといけない – 言語は? – どうやってビルドする? – Flux? –
Styleは? – ディレクトリ構成は? – テストは? • 導入当時の選択を振り返って、反省したい React周辺の技術スタック 10
シゴトでココロオドル • Tool – webpack, Babel, ESLint • Library –
Redux, Redux-thunk, Immutable.js – CSSModules, react-css-modules • Other – flux, E2E test 今の主な技術stack 11
シゴトでココロオドル Tools 12
シゴトでココロオドル • Railsからは切り離し、webpackを使っている – webpack-dev-server すごく便利 • 完全なSPAではない • 独立した機能から使い出して、独立したアプリケーション
がいっぱいできた – Entryファイルが機能ごとに分かれている • いざ全体にReactを入れていこうと思ったら、結構困った (困っている) webpack 13
シゴトでココロオドル webpack 14 • 各機能が独立しているので、一 緒に読み込めない • リンク一つで遷移できるはずな のに、ページのフルリロードが必 要
manage_posts.js analytics.js tickets.js messages.js
シゴトでココロオドル • こういうファイルが何個もある – それぞれが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]'), );
シゴトでココロオドル • 反省: アプリケーションは一つで、lazy loadで必要なも のだけ呼ぶようにする • webpackのdynamic importでできる –
ComponentやActionだけじゃなく、reducerもreplaceで きる • Storeやroutingの設定は一つになるように • 全体は一つのアプリケーションで、必要なページで追加の コードが読まれるように webpack 16
シゴトでココロオドル • もともと入れてなかった – Ruby側で使っていなかったから • すごいペースでコードが汚くなっていく – 使ってないのにimport –
中途半端なpropTypes – `==` vs `===` – 人間の目ではレビューしきれない • 途中から導入することに • 詳しくはこちらに – 全力で大きくなるReactのコードをスタイルガイドに沿って見直したら、大変勉強に なりました | Wantedly Engineer Blog ESLint 17
シゴトでココロオドル • 反省: 初めから入れて、徹底しよう • JSのコードは汚くなるもの • エディタでチェックするようにメンバーで共通する • レビューでは気づけないので、CIに入れてもいいかも
• 厳しめに入れて、後から緩くすればいい ESLint 18
シゴトでココロオドル Library 19
シゴトでココロオドル • Immutable便利 – Immutable.Recordでビジネスロジックを持ったオブジェ クトを作れる – OrderedSetなどのデータ構造もよく使う • どこはImmutableで、どこはPlainなのか
– ReducerごとのstateはPlain – EntityをImmutableでつくる – が、徹底して統一するのは難しい Immutable.js 20
シゴトでココロオドル • このオブジェクトは、Immutable? • この配列はArray or Immutable.List ? • propTypesも適当になってくる
– anyがいっぱい • どちらかに統一するというよりは、型が分か れば解決できる問題 – TypeScriptとかなら解決できる Immutable.js 21
シゴトでココロオドル • 状態管理を行うcomponent – 主にReduxとconnectするcomponent • どこからContainerで、どこからComponentにするか – ページ単位? –
Routing単位? – 実はどこでもいい Container(Redux) 22
シゴトでココロオドル • Containerは一番外側のcomponent、みたいに思って いたおかげで、propsの受け渡しが多すぎるひどいコード が増えた • すごく雑なpropTypesや、全部受け取るconnectの出 来上がり Container 23
export default connect( state => ({ analytics: state.analytics, }), dispatch => bindActionCreators({ ...actions }), )(AnalyticsContainer);
シゴトでココロオドル • もっと細かくContainerを分けるべき – 必要ないstateも受けていると、パフォーマンスが 下がる – 受け渡すだけのprosは、可読性も下がるし、書く のもかなり面倒さい •
ディレクトリ構成も一因に – Componentから遠いので、行き来するが面倒 – `import from ‘../../../containers/’;` Container 24
シゴトでココロオドル Language 25
シゴトでココロオドル • ES2015をbabelでトランスパイルしている • Stage-3まで使える – Candidateなので、大きく変わる可能性は小さい • それ以下は要相談 –
`static propTypes =` などは使っている – simpleで変わる心配少ない & 変わっても簡単に直せ る & 可読性がかなり上がる – TypeScriptでもかけるし。。 ES2015 26
シゴトでココロオドル • 型は必要だった? – Railsを書いている人が大部分なので、ハードル が高いと思った • CoffeeScriptからの差が大きい – 今はgolangとか書く人も増えてるし、型の良さも
共通認識である(と思う) – TypeScriptのIntelliSenseがいい ES2015 27
シゴトでココロオドル • 反省: TypeScriptにしても良かった – propTypesも標準じゃなくなるし – Googleでも標準言語になってるし – VS
Codeで生産性高いし • 途中からTypeScriptにするのは骨が折れ そうだから、初めからTSにできるならした方 がいい • Flowでも可 ES2015 28
シゴトでココロオドル Test 29
シゴトでココロオドル • 現:JSの単体テストはなく、Railsも含めたE2Eテストで担 保している • Wantedlyのwebエンジニアは、フロントもサーバーも一 人で書く場合が多い – バーっと動くものをつくって、重要なところをE2Eで担保 していくスタイルがあっていた
• Angular時代も単体テストを書く環境はあったが、ほとん ど書かれることはなかった テスト 30
シゴトでココロオドル • 反省: テストはかけた方がいい • 全てE2Eテストを書くのは大変 • 各Component書く必要はなさそう • ActionCreatorや、ビジネスロジックはテス
トが書かれるべき <- 当たり前 • 環境整えるのが大変なので、誰か助けてくだ さい テスト 31
シゴトでココロオドル Directory Structure 32
シゴトでココロオドル • react/ – components/ • {fooapp, barapp}/ – containers/
• {fooapp, barapp} – reducers/ • {fooapp, barapp} – actions/ • {fooapp, barapp} – lib/immutable/ ディレクトリ構成 33 • 外側は役割ごとに分けられて いる • その中は、機能ごとに同じよう に分けている • 実際はもうちょっと汚い • 初めはflatだった • 一つの機能が離れたところに
シゴトでココロオドル • StateとUIを分けるべき – アプリケーションの状態とUIのReactとは切り離す – ComponentsとContainerはディレクトリで分けなく ても良さそう • 関心ごとにまとめるべき
– 一つの機能に関するコードを近くに集めることで、 データの流れが追いやすくなる • 参考 – Automattic/wp-calypso ディレクトリ構成 34
シゴトでココロオドル • components/ – {fooapp, barapp}/ • Baz.jsx • BazContainer.js
• state/ – {fooapp, barapp}/ • action.js • reducer.js • selector.js • models/ ディレクトリ構成[理想] 35
シゴトでココロオドル Others 36
シゴトでココロオドル • CSSModulesを使っていた – CSSが分かれていて、デザイナーでも触りやすい – Rails側でscssを使っているので、変数の共有な どのために統一した • react-css-modules
– className={style.tabel} – styleName=’table’ – 書く量が減って、いいかなと思った CSS 37
シゴトでココロオドル • react-css-modulesのパフォーマンス – 実行時の解決なので、コストがかかる • babel-plugin-react-css-modules – BabelのCompile時に解決してくれるのでパフォー マンスがいい
– 何が起きてるかわかりにくいbabelのpluginは入れ たくない • 学習コストが上がる • なんでもできちゃう CSS 38
シゴトでココロオドル • シンプルにCSSModulesだけで良かった • className={s.table}って書くだけで、大し て面倒ではない – 直感的に理解できる – undefinedチェックとか実装時はうざいだけ
<= 設 定の問題 – camelCaseのスタイルでもいいじゃん CSS 39
シゴトでココロオドル • State treeからデータを取ってくる関数 – 離れた場所のデータを組みわせて使いたい場面 とかに便利 – redux/reselect を使うとメモ化なども行なってくれ、
パフォーマンスにも優しい • 初めは、render内で毎回計算したり、state に保存したりしていた Selector 40
シゴトでココロオドル • state treeの構造をどうするべきか – APIのデータをそのままstateに入れると、nestが 深くなる – 深いデータが更新されると、上側も全て更新され る
– パフォーマンス的にもよろしくない – データの一貫性を保つのが難しい • Reducerのコードが複雑になる Normalize 41
シゴトでココロオドル • 各entityごとにnestを均してから保存する – IDをkey, entityをvalueにしたMapに保存 – 元あった場所にはIDを入れておく – propsはIDを渡して、connectでentityを取ってくる
• 利点 – 関係ないデータが変更されても、updateが少なく なる – Reducerの処理がシンプルになる • IDからデータを探して更新するだけ Normalize 42
シゴトでココロオドル • Reduxのmiddleware – Actionのdispatchに割り込んで、色々できる • 非同期処理を扱うために、redux-thunkだ け入れた – Simpleでとにかく学習コストが低い
• Loggingなどの副作用や、共有化された APIコールなどで、適宜作っている • こういうところに単体テストがないの良くない middleware 43
シゴトでココロオドル まとめ 44
シゴトでココロオドル • React導入一年経って、うまくいっていると胸 を張って言える • チームの状況を見てスタックを選択しよう – Wantedlyは一人がサーバーとフロントを両方書く 体制 •
大きな失敗はないけど、もっとよくできたと反 省は絶えない • これから導入する人の参考になれば嬉しい まとめ 45
シゴトでココロオドル We are hiring! 46 https://www.wantedly.com/projects/59809