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

Scaling React.js Applications (short version)

Max Stoiber
September 16, 2016

Scaling React.js Applications (short version)

25 minute super-speed introduction to scaling react applications!

Max Stoiber

September 16, 2016
Tweet

More Decks by Max Stoiber

Other Decks in Technology

Transcript

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  6. @mxstbr
    Containers and Components

    View full-size slide

  7. @mxstbr
    Structure

    View full-size slide

  8. @mxstbr
    Traditionally grouped by type

    View full-size slide

  9. @mxstbr
    react-app-by-type
    !"" css
    !"" actions
    # $"" NavBarActions.js
    !"" containers
    # $"" NavBar.js
    !"" constants
    # $"" NavBarConstants.js
    !"" components
    # $"" App.js
    $"" reducers
    $"" NavBarReducer.js

    View full-size slide

  10. @mxstbr
    Group by feature instead

    View full-size slide

  11. @mxstbr
    react-app-by-feature
    !"" css
    !"" containers
    # $"" NavBar
    # !"" NavBar.js
    # !"" actions.js
    # !"" constants.js
    # $"" reducer.js
    $"" components
    $"" App.js

    View full-size slide

  12. @mxstbr
    Easy renaming and moving

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. @mxstbr
    Work in a single folder

    View full-size slide

  16. @mxstbr
    Reusable components

    View full-size slide

  17. @mxstbr
    Styling??

    View full-size slide

  18. @mxstbr
    .header {
    /* … */
    }
    .title {
    background-color: yellow;
    }
    .footer {
    /* … */
    }
    .title {
    border-color: blue;
    }
    Conflict!
    Naming

    View full-size slide

  19. @mxstbr
    CSS Modules

    View full-size slide

  20. @mxstbr
    import styles from ‘styles.css’;
    render() {
    return (
    className={styles.footer}
    />
    );
    }

    View full-size slide

  21. @mxstbr
    .footer { /* … */ }
    .title { /* … */ }
    .MyApp__footer__1co1k { /* … */ }
    .MyApp__title__2fgr5s { /* … */ }

    View full-size slide

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

    View full-size slide

  23. @mxstbr
    .header {
    line-height: 1.5em;
    }
    .title {
    line-height: 1.5em;
    }
    Inheritance
    .footer {
    line-height: 1em;
    }
    .title {
    line-height: 1em;
    }
    Conflict!

    View full-size slide

  24. @mxstbr
    Reset
    Header
    Title
    Global Reset
    Reset
    Header
    Local Reset
    Reset
    Title

    View full-size slide

  25. @mxstbr
    PostCSS

    View full-size slide

  26. @mxstbr
    PostCSS
    +
    postcss-autoreset

    View full-size slide

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

    View full-size slide

  28. @mxstbr
    react-app-by-feature
    !"" containers
    # $"" NavBar
    # !"" NavBar.js
    # !"" actions.js
    # !"" constants.js
    # !"" styles.css
    # $"" reducer.js
    $"" components
    $"" App.js

    View full-size slide

  29. @mxstbr
    Component Isolation!

    View full-size slide

  30. @mxstbr
    Data Fetching??

    View full-size slide

  31. @mxstbr
    redux-thunk?

    View full-size slide

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

    View full-size slide

  33. @mxstbr
    function fetchData() {
    return (dispatch) => {
    dispatch(dataFetching());
    fetch(‘myapi.com/‘, (data) => {
    // TODO: Error handling
    dispatch(dataFetched(data));
    });
    }
    }

    View full-size slide

  34. @mxstbr
    redux-saga

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  41. @mxstbr
    onStartClick={
    dipatch(startTimer())
    }
    />
    onStopClick={
    dispatch(showTime())
    }
    />

    View full-size slide

  42. @mxstbr
    onStartClick={
    dipatch(startClicked())
    }
    />
    onStopClick={
    dispatch(stopClicked())
    }
    />

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  48. @mxstbr
    Decoupled Components

    View full-size slide

  49. @mxstbr
    2. Group files by feature
    3. Isolate Styling
    1. Containers and Components
    4. Use redux-saga

    View full-size slide

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

    View full-size slide

  51. @mxstbr
    shouldComponentUpdate

    View full-size slide

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

    View full-size slide

  53. @mxstbr
    class NavBar extends React.Component {
    shouldComponentUpdate(nextProps) {
    return nextProps !== this.props;
    }
    }

    View full-size slide

  54. @mxstbr
    { “username”: “@mxstbr” } { “username”: “@mxstbr” }
    !==

    View full-size slide

  55. @mxstbr
    Deeply comparing objects
    is expensive

    View full-size slide

  56. @mxstbr
    ImmutableJS

    View full-size slide

  57. @mxstbr
    import { fromJS } from ‘immutable’;
    const state = fromJS({
    “username”: “@mxstbr”
    });

    View full-size slide

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

    View full-size slide

  59. @mxstbr
    Deeply comparing objects
    is cheap!

    View full-size slide

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

    View full-size slide

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

    View full-size slide