Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scaling React.js Applications

Scaling React.js Applications

48619fc17b3ab68472aebd56c0106278?s=128

Max Stoiber

July 04, 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. State Management 3. Architecture 1. What is Scalability?

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

    4. Performance
  9. @mxstbr 2. State Management 3. Architecture 1. What is Scalability?

    4. Performance
  10. @mxstbr

  11. @mxstbr

  12. @mxstbr

  13. @mxstbr Unidirectional Data Flow

  14. @mxstbr Store

  15. @mxstbr

  16. @mxstbr 2. State Management 3. Architecture 1. What is Scalability?

    4. Performance
  17. @mxstbr Containers and Components

  18. @mxstbr Structure

  19. @mxstbr Traditionally grouped by type

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

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

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

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

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

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

  26. @mxstbr Work in a single folder

  27. @mxstbr Reusable components

  28. @mxstbr Styling??

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

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

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

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

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

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

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

    Reset Title
  36. @mxstbr PostCSS

  37. @mxstbr PostCSS + postcss-autoreset

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

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

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

  41. @mxstbr Data Fetching??

  42. @mxstbr <Clock /> <Timer />

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

    />
  44. @mxstbr redux-saga

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

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

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

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

    yield take(STOP_BUTTON_CLICKED); put(stopTimer()); put(showTimeOnClock()); } }
  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 Decoupled Components

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

    Containers and Components 4. Use redux-saga
  53. @mxstbr 2. State Management 3. Architecture 1. What is Scalability?

    4. Performance
  54. @mxstbr Webpack Code Splitting

  55. @mxstbr

  56. @mxstbr

  57. @mxstbr

  58. @mxstbr

  59. @mxstbr

  60. @mxstbr shouldComponentUpdate

  61. @mxstbr

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

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

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

  65. @mxstbr Deeply comparing objects is expensive

  66. @mxstbr ImmutableJS

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

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

  69. @mxstbr Deeply comparing objects is cheap!

  70. @mxstbr

  71. @mxstbr

  72. @mxstbr 2. State Management 3. Architecture 1. What is Scalability?

    4. Performance
  73. Thanks for having me! Tweet comments/feedback to @mxstbr Come talk

    to me!