25 minute super-speed introduction to scaling react applications!
Scaling React.js ApplicationsMax Stoiber, @mxstbrOpen Source Developer, Thinkmill
View Slide
@mxstbr
KeystoneJS
ElementalUI
@mxstbr2. Architecture3. Performance1. What is Scalability?
“[Scalability] is thecapability of a systemto be enlarged…”Wikipedia
@mxstbrContainers and Components
@mxstbrStructure
@mxstbrTraditionally grouped by type
@mxstbrreact-app-by-type!"" css!"" actions# $"" NavBarActions.js!"" containers# $"" NavBar.js!"" constants# $"" NavBarConstants.js!"" components# $"" App.js$"" reducers$"" NavBarReducer.js
@mxstbrGroup by feature instead
@mxstbrreact-app-by-feature!"" css!"" containers# $"" NavBar# !"" NavBar.js# !"" actions.js# !"" constants.js# $"" reducer.js$"" components$"" App.js
@mxstbrEasy renaming and moving
@mxstbrimport { toggleNav } from ‘containers/NavBar/actions.js’;
@mxstbrimport { toggleNav } from ‘containers/PrimaryNav/actions.js’;
@mxstbrWork in a single folder
@mxstbrReusable components
@mxstbrStyling??
@mxstbr.header {/* … */}.title {background-color: yellow;}.footer {/* … */}.title {border-color: blue;}Conflict!Naming
@mxstbrCSS Modules
@mxstbrimport styles from ‘styles.css’;render() {return (className={styles.footer}/>);}
@mxstbr.footer { /* … */ }.title { /* … */ }.MyApp__footer__1co1k { /* … */ }.MyApp__title__2fgr5s { /* … */ }
@mxstbr.header { line-height: 1.5em; }a { line-height: 1.5em; }.title { line-height: 1.5em; }Inheritance
@mxstbr.header {line-height: 1.5em;}.title {line-height: 1.5em;}Inheritance.footer {line-height: 1em;}.title {line-height: 1em;}Conflict!
@mxstbrResetHeaderTitleGlobal ResetResetHeaderLocal ResetResetTitle
@mxstbrPostCSS
@mxstbrPostCSS+postcss-autoreset
@mxstbr.header { line-height: 1.5em; }a { line-height: default; }.title { line-height: default; }
@mxstbrreact-app-by-feature!"" containers# $"" NavBar# !"" NavBar.js# !"" actions.js# !"" constants.js# !"" styles.css# $"" reducer.js$"" components$"" App.js
@mxstbrComponent Isolation!
@mxstbrData Fetching??
@mxstbrredux-thunk?
@mxstbrfunction fetchData() {return (dispatch) => {dispatch(dataFetching());fetch(‘myapi.com/‘, (data) => {dispatch(dataFetched(data));});}}
@mxstbrfunction fetchData() {return (dispatch) => {dispatch(dataFetching());fetch(‘myapi.com/‘, (data) => {// TODO: Error handlingdispatch(dataFetched(data));});}}
@mxstbrredux-saga
@mxstbrfunction* fetchData() {while (true) {yield take(FETCH_DATA);put(dataFetching());const data = yield call(fetch(‘myapi.com/');put(dataFetched(data));}}
@mxstbrfunction* fetchData() {while (true) {yield take(FETCH_DATA);put(dataFetching());const data = yield call(fetch(‘myapi.com/');// TODO: Error handlingput(dataFetched(data));}}
@mxstbronStartClick={dipatch(startTimer())}/>onStopClick={dispatch(showTime())}/>
@mxstbronStartClick={dipatch(startClicked())}/>onStopClick={dispatch(stopClicked())}/>
@mxstbrfunction* connectClockToTimer() {while (true) {yield take(START_BUTTON_CLICKED);put(startTimer());yield take(STOP_BUTTON_CLICKED);put(stopTimer());put(showTimeOnClock());}}
@mxstbrDecoupled Components
@mxstbr2. Group files by feature3. Isolate Styling1. Containers and Components4. Use redux-saga
@mxstbrshouldComponentUpdate
@mxstbrclass NavBar extends React.Component {shouldComponentUpdate(nextProps) {?????}}
@mxstbrclass NavBar extends React.Component {shouldComponentUpdate(nextProps) {return nextProps !== this.props;}}
@mxstbr{ “username”: “@mxstbr” } { “username”: “@mxstbr” }!==
@mxstbrDeeply comparing objectsis expensive
@mxstbrImmutableJS
@mxstbrimport { fromJS } from ‘immutable’;const state = fromJS({“username”: “@mxstbr”});
@mxstbr.equalsfromJS({ “username”: “@mxstbr” })fromJS({ “username”: “@mxstbr” })
@mxstbrDeeply comparing objectsis cheap!
Thanks for having me!Tweet comments/feedback to @mxstbrCome talk to me!