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.5k
導入して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
5
3.6k
デザインシステムを導入してUIに秩序を取り戻す - React (Native)編 #rejectron2018
kentomoriwaki
16
3.5k
ReactでWebとNativeの共通UIライブラリを作ろう
kentomoriwaki
0
1.1k
BFFを導入しなかった理由
kentomoriwaki
4
13k
TypeScript in Wantedly
kentomoriwaki
2
660
5分でわかる React "Suspense"
kentomoriwaki
3
1.4k
Immutable.jsとReact @Wantedly ~入門編~
kentomoriwaki
8
74k
React速習会@Wantedly
kentomoriwaki
1
400
Other Decks in Programming
See All in Programming
NSOutlineView何もわからん:( 前編 / I Don't Understand About NSOutlineView :( Pt. 1
usagimaru
0
260
Java ジェネリクス入門 2024
nagise
0
680
Server Driven Compose With Firebase
skydoves
0
430
リアーキテクチャxDDD 1年間の取り組みと進化
hsawaji
1
180
リリース8年目のサービスの1800個のERBファイルをViewComponentに移行した方法とその結果
katty0324
5
4.1k
Tuning GraphQL on Rails
pyama86
2
1.2k
とにかくAWS GameDay!AWSは世界の共通言語! / Anyway, AWS GameDay! AWS is the world's lingua franca!
seike460
PRO
1
770
EventSourcingの理想と現実
wenas
6
2.2k
Snowflake x dbtで作るセキュアでアジャイルなデータ基盤
tsoshiro
2
490
Nurturing OpenJDK distribution: Eclipse Temurin Success History and plan
ivargrimstad
0
360
カスタムしながら理解するGraphQL Connection
yanagii
1
1.5k
GitHub Actionsのキャッシュと手を挙げることの大切さとそれに必要なこと
satoshi256kbyte
5
410
Featured
See All Featured
The Invisible Side of Design
smashingmag
297
50k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
How to Think Like a Performance Engineer
csswizardry
20
1.1k
A better future with KSS
kneath
238
17k
Imperfection Machines: The Place of Print at Facebook
scottboms
264
13k
Why Our Code Smells
bkeepers
PRO
334
57k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
364
24k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
42
2.2k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Gamification - CAS2011
davidbonilla
80
5k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
6
390
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
505
140k
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