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

Bring Your Web Application Architecture to the Next Level With React.JS

Bring Your Web Application Architecture to the Next Level With React.JS

React.JS is a very powerful library for building user interfaces and the new, cool kid in the JavaScript world. But it is also very interesting for creating a fast, maintainable and interactive web application. In this talk I'll show what React is all about and how you can combine and integrate it’s power with your web application, even if you have to render out HTML on the server side. Especially common pitfalls for getting data from your backend to React will be covered. The result will be a flexible, component based architecture that enables developers to take page elements, like a single "follow" button, and place it everywhere on the site without having to duplicate any backend code, JS, HTML, CSS or AJAX endpoints in the process.

Bastian Hofmann

April 10, 2016
Tweet

More Decks by Bastian Hofmann

Other Decks in Programming

Transcript

  1. Bring your web
    application to the
    next level with
    React.JS
    @BastianHofmann

    View Slide

  2. ?

    View Slide

  3. Application
    architecture

    View Slide

  4. Code and
    component
    re-use

    View Slide

  5. Rapid
    Development

    View Slide

  6. Handling large
    code-bases

    View Slide

  7. With React.js

    View Slide

  8. With small and
    independent
    components

    View Slide

  9. webserver
    HTML
    browser
    JS
    controller

    View Slide

  10. webserver
    HTML
    browser
    JS
    Ajax
    controller

    View Slide

  11. webserver
    HTML
    browser
    JS
    Ajax
    controller

    View Slide

  12. de duplication
    ode duplication
    code duplication
    code duplication
    code duplication
    code duplication
    code duplication
    code duplication
    code duplication
    code duplication
    code duplication
    code duplication
    code duplication
    code duplicatio
    code duplicat
    code duplic
    code dup
    code du
    code
    cod
    co
    co

    View Slide

  13. A few words
    about me

    View Slide

  14. View Slide

  15. View Slide

  16. http://speakerdeck.com/u/bastianhofmann

    View Slide

  17. Application
    architecture

    View Slide

  18. View Slide

  19. status quo

    View Slide

  20. webserver
    loadbalancer
    pgsql memcached mongodb
    services

    View Slide

  21. webserver

    View Slide

  22. webserver
    HTML
    browser
    JS
    Ajax
    controller

    View Slide

  23. View Slide

  24. MVC

    View Slide

  25. Duplication and
    only some Code re-
    use

    View Slide

  26. We can do
    better

    View Slide

  27. Small components
    over big controllers

    View Slide

  28. View Slide

  29. View Slide

  30. View Slide

  31. View Slide

  32. View Slide

  33. View Slide

  34. View Slide

  35. Self contained

    View Slide

  36. Can be used
    everywhere

    View Slide

  37. JS is part of the
    component

    View Slide

  38. CSS can be part of
    the component

    View Slide

  39. http://facebook.github.io/react/

    View Slide

  40. JavaScript UI Library

    View Slide

  41. Many small, self
    contained,
    reusable
    components

    View Slide

  42. var HelloMessage = React.createClass(

    {

    render: function () {

    return Hello {this.props.name};

    }

    }

    );


    ReactDOM.render(,
    mountNode);

    View Slide

  43. var Timer = React.createClass({

    getInitialState: function () {

    return {secs: 0};

    },

    tick: function () {

    this.setState({secs: this.state.secs + 1});

    },

    componentDidMount: function () {

    this.interval = setInterval(this.tick, 1000);

    },

    componentWillUnmount: function () {

    clearInterval(this.interval);

    },

    render: function () {

    return (
    Seconds Elapsed: {this.state.secs}
    );

    }

    });


    ReactDOM.render(, mountNode);

    View Slide

  44. var TodoList = React.createClass(

    {

    render: function () {

    var createItem = function (itemText) {

    return {itemText};

    };

    return (

    {this.props.items.map(createItem)}

    );

    }

    }

    );

    View Slide

  45. var TodoApp = React.createClass({

    render: function () {

    return (


    TODO



    );

    }

    });

    View Slide

  46. Getting the data in
    there

    View Slide

  47. PHP
    Backend
    JSON React
    Frontend

    View Slide

  48. PHP
    Backend
    JSON React
    Frontend

    View Slide

  49. PHP
    Backend
    JSON React
    Frontend

    View Slide

  50. PHP
    Backend
    JSON React
    Frontend

    View Slide

  51. var TodoApp = React.createClass({

    getInitialState: function () {

    return {items: […]};

    },

    render: function () {

    return (


    TODO



    );

    }

    });

    View Slide

  52. Problematic

    View Slide

  53. Remember

    View Slide

  54. Self-contained

    View Slide

  55. Reusable

    View Slide

  56. PHP
    Backend
    JSON React
    Frontend

    View Slide

  57. PHP
    Backend
    JSON React
    Frontend

    View Slide

  58. PHP
    Backend
    JSON React
    Frontend

    View Slide

  59. Overfetching

    View Slide

  60. Underfetching

    View Slide

  61. Solutions

    View Slide

  62. Flux Datastores

    View Slide

  63. PHP
    Backend
    React
    Frontend
    Datastores

    View Slide

  64. Requirements

    View Slide

  65. PHP
    Backend
    React
    Frontend

    View Slide

  66. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Institution
    Menu
    React
    Frontend

    View Slide

  67. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Menu
    PHP Backend
    Request
    Response
    Institution

    View Slide

  68. LeftColumn Image
    Menu
    React
    Frontend

    View Slide

  69. LeftColumn Image
    Menu
    Request
    Response
    PHP Backend

    View Slide

  70. Remember:
    self contained

    View Slide

  71. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Menu
    Account
    Account
    Account
    Account
    Account
    Publication1
    Publication2
    Publication3
    Institution

    View Slide

  72. Do not fetch data
    directly

    View Slide

  73. Sssssssllllooooowww

    View Slide

  74. Require stuff

    View Slide

  75. http://www.infoq.com/presentations/Evolution-of-Code-
    Design-at-Facebook/

    View Slide

  76. View Slide

  77. Widget Widget Widget Widget
    Preparer
    Resolver Resolver
    Services
    Connector Interfaces
    Connector Implementations

    View Slide

  78. Widget Widget Widget Widget
    Preparer
    Fetch Requirements
    Resolver Resolver
    Services
    Connector Interfaces
    Connector Implementations

    View Slide

  79. Widget Widget Widget Widget
    Preparer
    Resolver Resolver
    Services
    Connector Interfaces
    Connector Implementations
    Batch
    requirements
    and pass
    them to
    resolvers

    View Slide

  80. Widget Widget Widget Widget
    Preparer
    Resolver Resolver
    Services
    Connector Interfaces
    Connector Implementations
    Call Services as
    effective as possible
    (Multi-GET,...)

    View Slide

  81. Widget Widget Widget Widget
    Preparer
    Resolver Resolver
    Services
    Connector Interfaces
    Connector Implementations
    Attach fetched
    data to
    Requirements and
    pass them back to
    the preparer

    View Slide

  82. Widget Widget Widget Widget
    Preparer
    Resolver Resolver
    Services
    Connector Interfaces
    Connector Implementations
    Distribute fetched
    data to the widgets
    that required it

    View Slide

  83. public function collect() {

    return [

    new EntityRequirement(

    'account',

    Account::class,

    ['id' => $this->request->get('id')]

    ),

    ];

    }

    View Slide

  84. Request Cache

    View Slide

  85. Multi-GET

    View Slide

  86. Futures

    View Slide

  87. Data
    dependencies
    within a widget

    View Slide

  88. public function collect() {

    yield [

    new EntityRequirement(

    'account',

    Account::class,

    ['id' => $this->request->get('id')]

    ),

    ];


    yield [

    new ServiceRequirement(

    'scienceDisciplines',

    AccountService::class,

    'getScienceDisciplines',

    ['account' => $this->account]

    )

    ];

    }

    View Slide

  89. Assembling the tree

    View Slide

  90. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Menu
    PHP Backend
    Request
    Response
    Institution

    View Slide

  91. Widget
    Requirement

    View Slide

  92. var TodoApp = React.createClass({

    getInitialState: function () {

    return {items: […]};

    },

    render: function () {

    return (


    TODO



    );

    }

    });

    View Slide

  93. class PublicationKeywordSearch {


    public $publications;

    public $publicationListItems = [];


    public function collect() {

    yield [

    serviceRequirement(

    'publications',

    PublicationService::getCall()->getByKeywords(

    ['virology', 'cancer'], 10, 0

    )

    )

    ];

    foreach ($this->publications as $publication) {

    yield new WidgetRequirement(

    'publicationListItems',

    PublicationItem::CLASS,

    [
    'publicationId' => $publication->getId()
    ]

    );

    }

    }

    }

    View Slide

  94. class PublicationItem {


    public $publicationId;

    public $publication;


    public function collect() {

    yield new RequestDataRequirement('publicationId');

    yield [

    new EntityRequirement(

    'publication',

    Publication::class,

    ['id' => $this->publicationId]

    )

    ];

    }

    }

    View Slide

  95. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Menu
    Institution

    View Slide

  96. Getting the data to
    React.js

    View Slide

  97. public function getData() {

    return [

    'key' => 'value',

    'other' => 'data',

    'number' => 42,

    'subComponent' => $this->subComponent,

    'someArray' => [1, 2, 3],

    'subComponentList' => [
    $this->items[0], $this->items[1]
    ]

    ];

    }

    View Slide

  98. {

    "ParentComponent-1234": {

    "component": "ParentComponent.jsx",

    "id": "ParentComponent-1234",

    "data": {

    "key": "value",

    "other": "data",

    "number": 42,

    "subComponent": "SubComponent",

    "someArray": [1, 2, 3],

    "subComponentList": [ "ListItem-444", "ListItem-555"]

    }

    },

    "SubComponent": {

    "component": "SubComponent.jsx",

    "id": "SubComponent",

    "data": { "boolValue": true }

    },

    "ListItem-444": {

    "component": "ListItem",

    "id": "ListItem-444",

    "data": { "title": "444s title“ }

    },

    "ListItem-555": {

    "component": "ListItem",

    "id": "ListItem-555",

    "data": { "title": "555s title" }

    }

    }

    View Slide

  99. var React = require('react');

    var SubComponent = require('SubComponent');

    var ListItem = require('ListItem');


    module.exports = React.createClass(

    {

    displayName: 'ParentComponent',

    render: function () {

    var items = [];


    for (var key in this.props.subComponentList) {

    if (this.props.subComponentList.hasOwnProperty(key)) {

    items.push(




    );

    }

    }


    return (


    {this.props.other} Hello PHP {this.props.number}


    {items}


    );

    }

    }

    );

    View Slide

  100. var React = require('react');


    module.exports = React.createClass(

    {

    displayName: 'ListItem',

    render: function () {

    return (


    {this.props.title}


    );

    }

    }

    );

    View Slide

  101. GraphQL
    http://graphql.org/

    View Slide

  102. PHP
    Backend
    React
    Frontend
    GraphQL

    View Slide

  103. Server side
    rendering

    View Slide

  104. SEO

    View Slide

  105. Better user
    experience

    View Slide

  106. Several
    approaches

    View Slide

  107. http://pecl.php.net/package/v8js
    V8js

    View Slide

  108. Request
    HTML
    Preparer
    libV8
    React
    PHP process
    Data array
    Rendered HTML string

    View Slide

  109. NodeJS proxy

    View Slide

  110. Request
    HTML
    Preparer
    nodeJS Proxy
    React
    PHP process
    Data JSON
    Rendered
    HTML string

    View Slide

  111. NodeJS service

    View Slide

  112. Request
    HTML
    Preparer
    nodeJS service
    PHP process
    Data JSON
    Rendered HTML string
    React

    View Slide

  113. Whoa

    View Slide

  114. This looks awfully
    complicated to
    debug

    View Slide

  115. View Slide

  116. View Slide

  117. Benefits

    View Slide

  118. Enables developers
    to only focus on
    their components

    View Slide

  119. Rapid prototyping

    View Slide

  120. Easier Refactoring

    View Slide

  121. Easy re-using of
    components

    View Slide

  122. Error Handling

    View Slide

  123. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Menu
    Institution

    View Slide

  124. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Menu
    EXCEPTION
    Institution

    View Slide

  125. Profile Publications Publication
    Publication
    Publication
    LeftColumn Image
    Menu
    Institution

    View Slide

  126. Experiments (A/B Testing)

    View Slide

  127. Feature toggles

    View Slide

  128. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Menu
    Institution

    View Slide

  129. Profile Publications Publication
    Publication
    Publication
    AboutMeNew
    LeftColumn Image
    Menu
    Institution

    View Slide

  130. Caching of
    Components

    View Slide

  131. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Menu

    Institution

    View Slide

  132. Load components
    asynchronously

    View Slide

  133. Profile Publications Publication
    Publication
    Publication
    AboutMe
    LeftColumn Image
    Menu

    loadWidget('/aboutMe', function(w) {<br/>w.render({ replace : '#placeholder' });<br/>})
    Institution

    View Slide

  134. Conclusion?

    View Slide

  135. Think about your
    architecture

    View Slide

  136. Refactor and make
    it better
    continuously

    View Slide

  137. Frontend and
    backend are part
    of the same
    application

    View Slide

  138. Don't rewrite your
    whole codebase in
    one go

    View Slide

  139. https://joind.in/talk/1f1aa

    View Slide

  140. http://twitter.com/BastianHofmann
    http://lanyrd.com/people/BastianHofmann
    http://speakerdeck.com/u/bastianhofmann
    [email protected]

    View Slide