Scaling React.js Applications (short version)

48619fc17b3ab68472aebd56c0106278?s=47 Max Stoiber
September 16, 2016

Scaling React.js Applications (short version)

25 minute super-speed introduction to scaling react applications!

48619fc17b3ab68472aebd56c0106278?s=128

Max Stoiber

September 16, 2016
Tweet

Transcript

  1. Scaling React.js Applications Max Stoiber, @mxstbr Open Source Developer, Thinkmill

  2. @mxstbr

  3. KeystoneJS

  4. ElementalUI

  5. @mxstbr

  6. @mxstbr

  7. @mxstbr 2. Architecture 3. Performance 1. What is Scalability?

  8. @mxstbr 2. Architecture 3. Performance 1. What is Scalability?

  9. “[Scalability] is the capability of a system to be enlarged…”

    Wikipedia
  10. @mxstbr 2. Architecture 3. Performance 1. What is Scalability?

  11. @mxstbr Containers and Components

  12. @mxstbr Structure

  13. @mxstbr Traditionally grouped by type

  14. @mxstbr react-app-by-type !"" css !"" actions # $"" NavBarActions.js !""

    containers # $"" NavBar.js !"" constants # $"" NavBarConstants.js !"" components # $"" App.js $"" reducers $"" NavBarReducer.js
  15. @mxstbr Group by feature instead

  16. @mxstbr react-app-by-feature !"" css !"" containers # $"" NavBar #

    !"" NavBar.js # !"" actions.js # !"" constants.js # $"" reducer.js $"" components $"" App.js
  17. @mxstbr Easy renaming and moving

  18. @mxstbr import { toggleNav } from ‘containers/NavBar/actions.js’;

  19. @mxstbr import { toggleNav } from ‘containers/PrimaryNav/actions.js’;

  20. @mxstbr Work in a single folder

  21. @mxstbr Reusable components

  22. @mxstbr Styling??

  23. @mxstbr .header { /* … */ } .title { background-color:

    yellow; } .footer { /* … */ } .title { border-color: blue; } Conflict! Naming
  24. @mxstbr CSS Modules

  25. @mxstbr import styles from ‘styles.css’; render() { return ( <div

    className={styles.footer} /> ); }
  26. @mxstbr .footer { /* … */ } .title { /*

    … */ } .MyApp__footer__1co1k { /* … */ } .MyApp__title__2fgr5s { /* … */ }
  27. @mxstbr .header { line-height: 1.5em; } a { line-height: 1.5em;

    } .title { line-height: 1.5em; } Inheritance
  28. @mxstbr .header { line-height: 1.5em; } .title { line-height: 1.5em;

    } Inheritance .footer { line-height: 1em; } .title { line-height: 1em; } Conflict!
  29. @mxstbr Reset Header Title Global Reset Reset Header Local Reset

    Reset Title
  30. @mxstbr PostCSS

  31. @mxstbr PostCSS + postcss-autoreset

  32. @mxstbr .header { line-height: 1.5em; } a { line-height: default;

    } .title { line-height: default; }
  33. @mxstbr react-app-by-feature !"" containers # $"" NavBar # !"" NavBar.js

    # !"" actions.js # !"" constants.js # !"" styles.css # $"" reducer.js $"" components $"" App.js
  34. @mxstbr Component Isolation!

  35. @mxstbr Data Fetching??

  36. @mxstbr redux-thunk?

  37. @mxstbr function fetchData() { return (dispatch) => { dispatch(dataFetching()); fetch(‘myapi.com/‘,

    (data) => { dispatch(dataFetched(data)); }); } }
  38. @mxstbr function fetchData() { return (dispatch) => { dispatch(dataFetching()); fetch(‘myapi.com/‘,

    (data) => { // TODO: Error handling dispatch(dataFetched(data)); }); } }
  39. @mxstbr redux-saga

  40. @mxstbr function* fetchData() { while (true) { yield take(FETCH_DATA); put(dataFetching());

    const data = yield call(fetch(‘myapi.com/'); put(dataFetched(data)); } }
  41. @mxstbr function* fetchData() { while (true) { yield take(FETCH_DATA); put(dataFetching());

    const data = yield call(fetch(‘myapi.com/'); put(dataFetched(data)); } }
  42. @mxstbr function* fetchData() { while (true) { yield take(FETCH_DATA); put(dataFetching());

    const data = yield call(fetch(‘myapi.com/'); put(dataFetched(data)); } }
  43. @mxstbr function* fetchData() { while (true) { yield take(FETCH_DATA); put(dataFetching());

    const data = yield call(fetch(‘myapi.com/'); put(dataFetched(data)); } }
  44. @mxstbr function* fetchData() { while (true) { yield take(FETCH_DATA); put(dataFetching());

    const data = yield call(fetch(‘myapi.com/'); put(dataFetched(data)); } }
  45. @mxstbr function* fetchData() { while (true) { yield take(FETCH_DATA); put(dataFetching());

    const data = yield call(fetch(‘myapi.com/'); // TODO: Error handling put(dataFetched(data)); } }
  46. @mxstbr <Clock /> <Timer />

  47. @mxstbr <Clock onStartClick={ dipatch(startTimer()) } /> <Timer onStopClick={ dispatch(showTime()) }

    />
  48. @mxstbr <Clock onStartClick={ dipatch(startClicked()) } /> <Timer onStopClick={ dispatch(stopClicked()) }

    />
  49. @mxstbr function* connectClockToTimer() { while (true) { yield take(START_BUTTON_CLICKED); put(startTimer());

    yield take(STOP_BUTTON_CLICKED); put(stopTimer()); put(showTimeOnClock()); } }
  50. @mxstbr function* connectClockToTimer() { while (true) { yield take(START_BUTTON_CLICKED); put(startTimer());

    yield take(STOP_BUTTON_CLICKED); put(stopTimer()); put(showTimeOnClock()); } }
  51. @mxstbr function* connectClockToTimer() { while (true) { yield take(START_BUTTON_CLICKED); put(startTimer());

    yield take(STOP_BUTTON_CLICKED); put(stopTimer()); put(showTimeOnClock()); } }
  52. @mxstbr function* connectClockToTimer() { while (true) { yield take(START_BUTTON_CLICKED); put(startTimer());

    yield take(STOP_BUTTON_CLICKED); put(stopTimer()); put(showTimeOnClock()); } }
  53. @mxstbr function* connectClockToTimer() { while (true) { yield take(START_BUTTON_CLICKED); put(startTimer());

    yield take(STOP_BUTTON_CLICKED); put(stopTimer()); put(showTimeOnClock()); } }
  54. @mxstbr Decoupled Components

  55. @mxstbr 2. Group files by feature 3. Isolate Styling 1.

    Containers and Components 4. Use redux-saga
  56. @mxstbr 2. Architecture 3. Performance 1. What is Scalability?

  57. @mxstbr

  58. @mxstbr

  59. @mxstbr

  60. @mxstbr

  61. @mxstbr

  62. @mxstbr shouldComponentUpdate

  63. @mxstbr

  64. @mxstbr class NavBar extends React.Component { shouldComponentUpdate(nextProps) { ????? }

    }
  65. @mxstbr class NavBar extends React.Component { shouldComponentUpdate(nextProps) { return nextProps

    !== this.props; } }
  66. @mxstbr { “username”: “@mxstbr” } { “username”: “@mxstbr” } !==

  67. @mxstbr Deeply comparing objects is expensive

  68. @mxstbr ImmutableJS

  69. @mxstbr import { fromJS } from ‘immutable’; const state =

    fromJS({ “username”: “@mxstbr” });
  70. @mxstbr .equals fromJS({ “username”: “@mxstbr” }) fromJS({ “username”: “@mxstbr” })

  71. @mxstbr Deeply comparing objects is cheap!

  72. @mxstbr

  73. @mxstbr

  74. @mxstbr 2. Architecture 3. Performance 1. What is Scalability?

  75. Thanks for having me! Tweet comments/feedback to @mxstbr Come talk

    to me!