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

React Native: Under the Hood

React Native: Under the Hood

Alexander Kotliarskyi

June 09, 2015
Tweet

More Decks by Alexander Kotliarskyi

Other Decks in Programming

Transcript

  1. React Native:

    Under the hood
    Alex Kotliarskyi
    Facebook

    View Slide

  2. Plan
    1. Why native apps matter?
    2. How ReactJS works
    3. Running ReactJS on native platforms

    View Slide

  3. Why do we



    native apps?

    View Slide

  4. Native Apps
    • Fast, responsive
    • Complex gestures and smooth animations
    • Consistent with platform

    View Slide

  5. View Slide

  6. Building native apps is hard
    • Different stacks of technologies
    • No knowledge and code sharing
    • Slow iteration speed
    • Hard to scale

    View Slide

  7. Web got this right

    View Slide

  8. Web
    • Different stacks of technologies
    • No knowledge and code sharing
    • Slow iteration speed
    • Hard to scale
    HTML / CSS / JS
    Same code and tech
    F5 / ⌘R
    React!

    View Slide

  9. Web apps on the phone are not great
    • Very hard to provide smooth experiences
    • Not designed for complex interactions
    • Impossible to embed native components

    View Slide

  10. Development
    experience
    Awesome

    apps

    View Slide

  11. React Native

    View Slide

  12. View Slide

  13. UI = ƒ*(data)
    * No side effects

    View Slide

  14. View Slide

  15. UI = ƒ(count)

    View Slide

  16. UI = ƒ(count) =

    div(
    span('Count ' + count),
    button('Add +1')
    )

    View Slide

  17. render()  {  
       return  (  
           div(  
               span(  
                   'Count:  '  +  b(this.state.count)  
               ),  
               button(  
                   'Add  +1'  
               )  
           )  
       )  
    }

    View Slide

  18. render()  {  
       return  (  
             
                 
                   Count:  {this.state.count}  
                 
                 
                   Add  +1  
                 
             
       )  
    }
    HTML
    VirtualDOM

    View Slide

  19. render()  {  
       return  (  
             
                 
                   Count:  {this.state.count}  
                 
                 ???  }>  
                   Add  +1  
                 
             
       )  
    }

    View Slide

  20. TextView  text  =  (TextView)findViewByID(R.layout.label);  
    text.setText('10');
    _label.text  =  @"10"; too complex
    Android
    Objective-C
    JavaScript
    document.getElementByID('count').children[1].innerHTML  =  '10';  
    $('#counter  b').html('10');

    View Slide

  21. render()  {  
       var  count  =  this.state.count;  
       return  (  
             
                 
                   Count:  {count}  
                 
                 ???  }>  
                   Add  +1  
                 
             
       )  
    }

    View Slide

  22. render()  {  
       var  count  =  this.state.count;  
       return  (  
             
                 
                   Count:  {count}  
                 
                 this.setState({count:  count  +  1})}>  
                   Add  +1  
                 
             
       )  
    }
    setState

    View Slide

  23. setState

    View Slide

  24.        
                 
                   Count:  9  
                 
                 
                   Add  +1  
                 
           
           
                 
                   Count:  10  
                 
                 
                   Add  +1  
                 
           
    state  =  {count:  9} state  =  {count:  10}
    9
    9 10
    findDOMNode(b).innerHTML  =  '10';

    View Slide

  25. Components
    Browser DOM
    UIKit
    Components Components Components
    VirtualDOM

    View Slide

  26. 1. Runtime
    2.Base components
    3. Calling native functions

    View Slide

  27. ECMAScript 5

    View Slide

  28. JavaScript Core
    • Part of WebKit project
    • Open Source
    • Ships with iOS
    Runtime

    View Slide

  29.  
     

     
     

     
     
     
     
    ...
    Base components

    View Slide

  30. create(view, parent, attributes)*

    update(view, attributes)
    delete(view)
    * actually React is more complex that that

    View Slide

  31. Just call native functions?
    nope

    View Slide

  32. Synchronous

    View Slide

  33. Native Method
    JavaScript
    time
    Waiting…

    View Slide

  34. JavaScript
    time
    Native JavaScript Native

    View Slide

  35. Synchronous
    Asynchronous

    View Slide

  36. Overhead of

    every

    native call

    View Slide

  37. JavaScript
    time

    View Slide

  38. time
    JavaScript

    View Slide

  39. Overhead of

    every

    native call
    Batch

    native calls

    View Slide

  40. Shared

    mutable

    data

    View Slide

  41. Native Objects
    JavaScript

    Objects

    View Slide

  42. Shared

    mutable

    data
    Exchange

    serializable

    messages

    View Slide

  43. Asynchronous
    Batched
    Serializable

    View Slide

  44. The Bridge

    View Slide

  45. Native
    Bridge
    JavaScript

    View Slide

  46. Native
    Bridge
    JavaScript
    Event

    (touch, timer, networks, etc.)
    1
    Collect data and notify JS
    2
    Serialized payload
    3
    Process event
    4
    Call 0 – ∞
    native methods
    5
    Update UI

    (if needed)
    8
    Serialized response
    6
    Process commands
    7

    View Slide

  47. JS is event-driven

    View Slide

  48. Events Commands

    View Slide

  49. Example

    View Slide

  50. • Updates counter
    • Sends data to web service

    View Slide

  51.    render()  {  
           return  (  
                 
                     
                       {this.state.count}  
                     
                                       title="Add  +1"  
                       onPress={()  =>  this.inc()}  
                   />  
                 
           );  
       }

    View Slide

  52.    inc()  {  
           var  newCount  =  this.state.count  +  1;  
           this.setState({count:  newCount});  
           fetch(  
               'https://api.conunter.io/',  
               {  
                   method:  'post',  
                   body:  'value='  +  newCount  
               }  
           );  
       }

    View Slide

  53. Native
    UITouch
    [_bridge enqueueJSCall:@"EventEmitter.receiveTouches"
    args:@[@"end",
    @{@"x": @42, @"y": @106}]];
    x, y, view, ...

    View Slide

  54. Native
    Bridge
    JavaScript
    [
    'EventEmitter', 'receiveTouches',
    ['end', {'x': 42, 'y': 106}]
    ]
    [_bridge enqueueJSCall:@"RCTEventEmitter.receiveTouches"
    args:@[@"end",
    @{@"x": @42, @"y": @106}]];
    call('EventEmitter',  'receiveTouches',  [{x:  42,  y:  ...}])

    View Slide

  55. function  call(moduleName,  methodName,  args)  {  
       MessageQueue.init();  
         
       var  module  =  require(moduleName);  
       module[methodName].apply(module,  args);  
         
       return  MessageQueue.flush();  
    }
    //  EventEmitter
    //  receiveTouches
    Message

    queue

    View Slide

  56. Touch processing

    View Slide

  57. What element

    should respond

    to a given event?

    View Slide

  58. Button
    Button pressed!

    View Slide

  59. Button
    Cancelled

    View Slide

  60. Button
    Cancelled
    Scrollview

    View Slide

  61. Button
    Scrolling stops
    Scrollview

    View Slide

  62. Button
    Scrollview
    Horizontal Scrollview
    Navigator

    View Slide

  63. Responder System

    View Slide

  64. onStartShouldSetResponder
    onResponderTerminationRequest
    onResponderGrant
    onResponderMove
    onResponderRelease
    onResponderTerminate

    View Slide





  65. onPress

    View Slide

  66.    inc()  {  
           var  newCount  =  this.state.count  +  1;  
           this.setState({count:  newCount});  
           fetch(  
               'https://api.conunter.io/',  
               {  
                   method:  'post',  
                   body:  'value='  +  newCount  
               }  
           );  
       }

    View Slide

  67.            
                     
                       42  
                     
                                       title="Add  +1"  
                       onPress={...}  
                   />  
               
               
                     
                       43  
                     
                                       title="Add  +1"  
                       onPress={...}  
                   />  
               
    42 43

    View Slide

  68. var  UIManager  =  require('NativeModules').UIManager;  
    UIManager.update(18,  {text:  '43'});
    Somewhere in React's internals:

    View Slide

  69. NativeModules

    View Slide

  70. NativeModules.UIManager  =  {  
       ...  
       update:  function(viewID,  attributes)  {  
           MessageQueue.push(  
               ['UIManager',  'update',  [viewID,  attributes]]  
           );  
       }  
       ...  
    };
    Message

    queue
    UIManager

    update  ..

    View Slide

  71.    inc()  {  
           var  newCount  =  this.state.count  +  1;  
           this.setState({count:  newCount});  
           fetch(  
               'https://api.conunter.io/',  
               {  
                   method:  'post',  
                   body:  'value='  +  newCount  
               }  
           );  
       }
    Message

    queue
    UIManager

    update  ..
    DataManager

    query    ....

    View Slide

  72. function  call(moduleName,  methodName,  args)  {  
       MessageQueue.init();  
         
       var  module  =  require(moduleName);  
       module[methodName].apply(module,  args);  
         
       return  MessageQueue.flush();  
    }
    Message

    queue
    UIManager

    update  ..
    DataManager

    query    ....

    View Slide

  73. Native
    Bridge
    JavaScript
    [UIManager updateView:18 props:@{@"text": @"43"}]
    [DataManager query:@"post" url:@"http://..."]
    [
    ['UIManager', 'update', [18, {text: '43'}]],
    ['DataManager', 'query', ['post', 'http://...']]
    ]
    Message

    queue
    UIManager

    update  ..
    DataManager

    query    ....

    View Slide

  74. Native
    [UIManager updateView:18 props:@{@"text": @"43"}]
    addUIBlock:^() {
    UILabel *label = viewRegistry[18];
    label.text = @"43";
    [label markAsDirty];
    }

    View Slide

  75. Layout
    Layout
    github.com/facebook/css-layout

    View Slide

  76. {
    margin: 20,
    borderBottomWidth: 2,
    flex: 1,
    alignContent: 'center',
    }
    {
    left: 120,
    top: 220,
    width: 60,
    height: 60,
    }
    Flexbox Coordinates

    View Slide

  77. • User taps the button
    • Counter is updated

    View Slide

  78. Native
    Bridge
    JavaScript
    Event

    (touch, timer, networks, etc.)
    1
    Collect data and notify JS
    2
    Serialized payload
    3
    Process event
    4
    Call 0 – ∞
    native methods
    5
    Serialized response
    6
    Process commands
    7
    Update UI

    (if needed)
    8

    View Slide

  79. Benefits

    View Slide

  80. Fast

    View Slide

  81. Native
    Bridge
    JavaScript
    Event

    (touch, timer, networks, etc.)
    1 Update UI

    (if needed)
    8
    Collect data and notify JS
    2
    Serialized payload
    3
    Process event
    4
    Call 0 – ∞
    native methods
    5
    Serialized response
    6
    Process commands
    7

    View Slide

  82. Record / Replay

    View Slide

  83. Flexible JS runtime

    View Slide

  84. Native
    Bridge
    JavaScript

    View Slide

  85. Native
    Bridge
    JavaScript
    Awesome App

    View Slide

  86. Native
    Bridge
    JavaScript
    Awesome App
    WebKit process
    IPC

    View Slide

  87. Native
    Bridge
    JavaScript
    Awesome App
    Chrome Debugger
    WebSockets

    View Slide

  88. Live demo iPhone -> Chrome

    View Slide

  89. View Slide

  90. View Slide

  91. Heroku
    iPhone

    View Slide

  92. Streaming

    View Slide

  93. View Slide

  94. UI = ƒ(data)

    View Slide

  95. Thank you!
    github.com/frantic/tlv-2015
    @alex_frantic

    View Slide