$30 off During Our Annual Pro Sale. View Details »

Hastening React SSR with component memoization and templatization

Hastening React SSR with component memoization and templatization

Hastening React SSR with component memoization and templatization: React is a best-of-breed UI component framework allowing WalmartLabs to build higher level components that can be shared and reused across pages and apps. In this presentation, Max Najim and Naga Malepati from WalmartLabs will peel through the React codebase to add a component caching/memoization optimization. The will use a require(..) hook to inject their optimization while avoiding the need to fork the React codebase.

Maxime Najim

August 11, 2016
Tweet

More Decks by Maxime Najim

Other Decks in Programming

Transcript

  1. HASTENING REACT SSR WITH
    COMPONENT MEMOIZATION
    AND TEMPLATIZATION

    View Slide

  2. Increasing User Demand
    www.radware.com
    Web App Performance

    View Slide

  3. •For every 1 second of
    improvement, experienced up to
    a 2% increase in conversions
    •For every 100 ms of
    improvement, grew incremental
    revenue by up to 1%
    Time is Money
    Source: http://www.globaldots.com/how-website-speed-affects-conversion-rates

    View Slide

  4. Server-Side Rendering (SSR)
    •Better user experience of
    the initial page load

    •Better search engine ranking

    View Slide

  5. SSR with React

    View Slide

  6. Server-Side React
    Bad User Experience!

    View Slide

  7. Server-Side React
    CPU profile for one request
    On large pages, renderToString(.) blocks
    nodeJS’s event-loop and starves out
    incoming requests to the server.

    View Slide

  8. Server-Side React
    • Facebook: “Funny story about Server
    Rendering - it wasn’t actually
    designed that way.” (Sebastian
    Markbåge)
    • Facebook: “we don’t use it that
    heavily, which is why we haven’t really
    invested strongly in it.” (Sebastian
    Markbåge)
    React.js Conf 2015 

    Q&A with the team
    https://youtu.be/EPpkboSKvPI?t=7m48s

    View Slide

  9. Server-Side React
    0
    325ms
    650ms
    975ms
    1s 300ms
    React React (best practices) mustache
    https://github.com/ndreckshage/react-boston-ssr

    View Slide

  10. • Looked at react-dom-stream and
    redfin/react-server to improve TTFB
    and ATF improvement
    • Challenges
    • Forks react and introduces new
    interfaces, i.e. not “React at heart”
    • Doesn't solve CPU total time
    Server-Side React
    ReactJS SF meetup in January 2016
    https://github.com/aickin/react-dom-stream

    View Slide

  11. React Rendering Lifecycle
    getDefaultProps()
    getInitialState()
    componentWillMount()
    render()
    componentDidMount()
    Create Component
    Instance
    Create Transaction
    Mount Component
    (Gen Markup)
    Transaction.enqueue
    componentInstance
    Transaction.dequeue

    View Slide

  12. Mount Component
    React EL with Props Markup
    Given a set of properties, the markup generated is always the same
    Component Cache
    Double Clicking into Mount Component

    View Slide

  13. Memoizing Components
    The same “text” prop will always return
    the same helloworld html string
    class HelloWorldComponent extends React.Component {
    render() {
    return Hello {this.props.text}!;
    }
    }
    When text is “World” the output is:
    Hello World!

    View Slide

  14. Memoizing Components
    The same “text” prop will always return
    the same helloworld html string
    class HelloWorldComponent extends React.Component {
    render() {
    return Hello {this.props.text}!;
    }
    }
    When text is “World” the output is:
    Hello World!
    var componentOptimization =
    require("electrode-react-ssr-
    optimization");
    var componentOptimizationRef =
    componentOptimization({
    components: {
    'HelloWorldComponent': {

    keyAttrs: ["text"]
    }
    }
    });

    View Slide

  15. Memoizing Demo

    View Slide

  16. Templatizing Components
    var React = require('react');
    var ProductView = React.createClass({
    render: function() {
    return (



    {this.props.product.name}
    {this.props.product.description}
    Price: ${this.props.product.price}
    disabled={this.props.inventory > 0 ? '' : 'disabled'}>
    Add To Cart



    );
    }
    });
    module.exports = ProductView;

    View Slide

  17. Templatizing Components
    var React = require('react');
    var ProductView = React.createClass({
    render: function() {
    return (



    {this.props.product.name}
    {this.props.product.description}
    Price: ${this.props.product.price}
    disabled={this.props.inventory > 0 ? '' : 'disabled'}>
    Add To Cart



    );
    }
    });
    module.exports = ProductView;
    • Dynamic props that would be
    different for each product.

    • Switch the corresponding props
    with template delimiters 

    (i.e. ${ prop_name }) during react
    component rendering cycle.
    • The template is then compiled,
    cached, executed and the
    markup is handed back to React.

    View Slide

  18. Templatizing Components
    • Dynamic props that would be
    different for each product.

    • Switch the corresponding props
    with template delimiters 

    (i.e. ${ prop_name }) during react
    component rendering cycle.
    • The template is then compiled,
    cached, executed and the
    markup is handed back to React.



    ${product_name}
    ${product_description}
    Price: ${selected_price}

    Add To Cart



    View Slide

  19. Templatizing Components
    var React = require('react');
    var ProductView = React.createClass({
    render: function() {
    return (



    {this.props.product.name}
    {this.props.product.description}
    Price: ${this.props.product.price}
    disabled={this.props.inventory > 0 ? '' : 'disabled'}>
    Add To Cart



    );
    }
    });
    module.exports = ProductView;
    var componentOptimization =
    require("electrode-react-ssr-
    optimization");
    var componentOptimizationRef =
    componentOptimization({
    components: {
    "ProductView": {
    templateAttrs: ["product.image",

    "product.name", 

    "product.description", 

    "product.price"]
    },
    }
    });

    View Slide

  20. Templatizing Components
    var React = require('react');
    var ProductView = React.createClass({
    render: function() {
    return (



    {this.props.product.name}
    {this.props.product.description}
    Price: ${this.props.product.price}
    disabled={this.props.inventory > 0 ? '' : 'disabled'}>
    {this.props.inventory ? 'Add To Cart' : 'Sold Out'}



    );
    }
    });
    module.exports = ProductView;

    View Slide

  21. Templatizing Components
    var componentOptimization =
    require("electrode-react-ssr-
    optimization");
    var componentOptimizationRef =
    componentOptimization({
    components: {
    "ProductView": {
    templateAttrs: ["product.image",

    "product.name", 

    "product.description", 

    “product.price”],
    keyAttrs: ["product.inventory"]
    },
    }
    });
    var React = require('react');
    var ProductView = React.createClass({
    render: function() {
    return (



    {this.props.product.name}
    {this.props.product.description}
    Price: ${this.props.product.price}
    disabled={this.props.inventory > 0 ? '' : 'disabled'}>
    {this.props.inventory ? 'Add To Cart' : 'Sold Out'}



    );
    }
    });
    module.exports = ProductView;

    View Slide

  22. Templatizing Components



    ${product_name}
    ${product_description}
    Price: ${selected_price}

    Add To Cart






    ${product_name}
    ${product_description}
    Price: ${selected_price}

    Sold Out



    Cached Template 1 - Sold Out Cached Template 2 - Add To Cart

    View Slide

  23. Templatizing Demo

    View Slide

  24. green blocks indicating markup that was cached on the server

    View Slide

  25. Server-Side React
    CPU profile for one request
    with rendering optimization

    View Slide

  26. Thank You
    https://github.com/walmartlabs/electrode-react-ssr-optimization

    View Slide