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.7k
デザインシステムを導入して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
タクシーアプリ『GO』のリアルタイムデータ分析基盤における機械学習サービスの活用
mot_techtalk
4
1.5k
subpath importsで始めるモック生活
10tera
0
310
AI時代におけるSRE、 あるいはエンジニアの生存戦略
pyama86
6
1.2k
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
2
1.1k
ヤプリ新卒SREの オンボーディング
masaki12
0
130
Laravel や Symfony で手っ取り早く OpenAPI のドキュメントを作成する
azuki
2
120
聞き手から登壇者へ: RubyKaigi2024 LTでの初挑戦が 教えてくれた、可能性の星
mikik0
1
130
Contemporary Test Cases
maaretp
0
140
Why Jakarta EE Matters to Spring - and Vice Versa
ivargrimstad
0
1.1k
GitHub Actionsのキャッシュと手を挙げることの大切さとそれに必要なこと
satoshi256kbyte
5
430
レガシーシステムにどう立ち向かうか 複雑さと理想と現実/vs-legacy
suzukihoge
14
2.2k
色々なIaCツールを実際に触って比較してみる
iriikeita
0
330
Featured
See All Featured
Git: the NoSQL Database
bkeepers
PRO
427
64k
Designing on Purpose - Digital PM Summit 2013
jponch
115
7k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
The Language of Interfaces
destraynor
154
24k
Adopting Sorbet at Scale
ufuk
73
9.1k
Building Adaptive Systems
keathley
38
2.3k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
0
100
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.2k
Into the Great Unknown - MozCon
thekraken
32
1.5k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
246
1.3M
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
720
Intergalactic Javascript Robots from Outer Space
tanoku
269
27k
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