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

React Native: Under the Hood

React Native: Under the Hood

09f29a1cb5a7c670532ba4bb1b224758?s=128

Alexander Kotliarskyi

June 09, 2015
Tweet

Transcript

  1. React Native:
 Under the hood Alex Kotliarskyi Facebook

  2. Plan 1. Why native apps matter? 2. How ReactJS works

    3. Running ReactJS on native platforms
  3. Why do we
 ❤ 
 native apps?

  4. Native Apps • Fast, responsive • Complex gestures and smooth

    animations • Consistent with platform
  5. None
  6. Building native apps is hard • Different stacks of technologies

    • No knowledge and code sharing • Slow iteration speed • Hard to scale
  7. Web got this right

  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!
  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
  10. Development experience Awesome
 apps

  11. React Native

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

  14. None
  15. UI = ƒ(count)

  16. UI = ƒ(count) =
 div( span('Count ' + count), button('Add

    +1') )
  17. render()  {      return  (        

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

     <div>              <span>                  Count:  <b>{this.state.count}</b>              </span>              <button>                  Add  +1              </button>          </div>      )   } HTML VirtualDOM
  19. render()  {      return  (        

     <div>              <span>                  Count:  <b>{this.state.count}</b>              </span>              <button  onClick={()  =>  ???  }>                  Add  +1              </button>          </div>      )   }
  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');
  21. render()  {      var  count  =  this.state.count;    

     return  (          <div>              <span>                  Count:  <b>{count}</b>              </span>              <button  onClick={()  =>  ???  }>                  Add  +1              </button>          </div>      )   }
  22. render()  {      var  count  =  this.state.count;    

     return  (          <div>              <span>                  Count:  <b>{count}</b>              </span>              <button  onClick={()  =>  this.setState({count:  count  +  1})}>                  Add  +1              </button>          </div>      )   } setState
  23. setState

  24.      <div>              <span>

                     Count:  <b>9</b>              </span>              <button>                  Add  +1              </button>          </div>      <div>              <span>                  Count:  <b>10</b>              </span>              <button>                  Add  +1              </button>          </div> state  =  {count:  9} state  =  {count:  10} <b>9</b> <b>9</b> <b>10</b> findDOMNode(b).innerHTML  =  '10';
  25. Components Browser DOM UIKit Components Components Components VirtualDOM

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

  27. ECMAScript 5

  28. JavaScript Core • Part of WebKit project • Open Source

    • Ships with iOS Runtime
  29. <div>   <span>   <img> <View>   <Text>   <Image>

    <ScrollView>   <MapView>   <TabBar>   <DatePicker>   ... Base components
  30. create(view, parent, attributes)*
 update(view, attributes) delete(view) * actually React is

    more complex that that
  31. Just call native functions? nope

  32. Synchronous

  33. Native Method JavaScript time Waiting…

  34. JavaScript time Native JavaScript Native

  35. Synchronous Asynchronous

  36. Overhead of
 every
 native call

  37. JavaScript time

  38. time JavaScript

  39. Overhead of
 every
 native call Batch
 native calls

  40. Shared
 mutable
 data

  41. Native Objects JavaScript
 Objects

  42. Shared
 mutable
 data Exchange
 serializable
 messages

  43. Asynchronous Batched Serializable

  44. The Bridge

  45. Native Bridge JavaScript

  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
  47. JS is event-driven

  48. Events Commands

  49. Example

  50. • Updates counter • Sends data to web service

  51.    render()  {          return  (  

               <View  style={styles.container}>                  <Text  style={styles.value}>                      {this.state.count}                  </Text>                  <Button                      title="Add  +1"                      onPress={()  =>  this.inc()}                  />              </View>          );      }
  52.    inc()  {          var  newCount  =

     this.state.count  +  1;          this.setState({count:  newCount});          fetch(              'https://api.conunter.io/',              {                  method:  'post',                  body:  'value='  +  newCount              }          );      }
  53. Native UITouch [_bridge enqueueJSCall:@"EventEmitter.receiveTouches" args:@[@"end", @{@"x": @42, @"y": @106}]]; x,

    y, view, ...
  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:  ...}])
  55. function  call(moduleName,  methodName,  args)  {      MessageQueue.init();    

           var  module  =  require(moduleName);      module[methodName].apply(module,  args);            return  MessageQueue.flush();   } //  EventEmitter //  receiveTouches Message
 queue
  56. Touch processing

  57. What element
 should respond
 to a given event?

  58. Button Button pressed!

  59. Button Cancelled

  60. Button Cancelled Scrollview

  61. Button Scrolling stops Scrollview

  62. Button Scrollview Horizontal Scrollview Navigator

  63. Responder System

  64. onStartShouldSetResponder onResponderTerminationRequest onResponderGrant onResponderMove onResponderRelease onResponderTerminate …

  65. <TouchableOpacity>
 <TouchableHighlight>
 <TouchableBounce>
 <TouchableWithoutFeedback> onPress

  66.    inc()  {          var  newCount  =

     this.state.count  +  1;          this.setState({count:  newCount});          fetch(              'https://api.conunter.io/',              {                  method:  'post',                  body:  'value='  +  newCount              }          );      }
  67.          <View  style={...}>        

             <Text  style={...}>                      42                  </Text>                  <Button                      title="Add  +1"                      onPress={...}                  />              </View>          <View  style={...}>                  <Text  style={...}>                      43                  </Text>                  <Button                      title="Add  +1"                      onPress={...}                  />              </View> 42 43
  68. var  UIManager  =  require('NativeModules').UIManager;   UIManager.update(18,  {text:  '43'}); Somewhere in

    React's internals:
  69. NativeModules

  70. NativeModules.UIManager  =  {      ...      update:  function(viewID,

     attributes)  {          MessageQueue.push(              ['UIManager',  'update',  [viewID,  attributes]]          );      }      ...   }; Message
 queue UIManager
 update  ..
  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    ....
  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    ....
  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    ....
  74. Native [UIManager updateView:18 props:@{@"text": @"43"}] addUIBlock:^() { UILabel *label =

    viewRegistry[18]; label.text = @"43"; [label markAsDirty]; }
  75. Layout Layout github.com/facebook/css-layout

  76. { margin: 20, borderBottomWidth: 2, flex: 1, alignContent: 'center', }

    { left: 120, top: 220, width: 60, height: 60, } Flexbox Coordinates
  77. • User taps the button • Counter is updated

  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
  79. Benefits

  80. Fast

  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
  82. Record / Replay

  83. Flexible JS runtime

  84. Native Bridge JavaScript

  85. Native Bridge JavaScript Awesome App

  86. Native Bridge JavaScript Awesome App WebKit process IPC

  87. Native Bridge JavaScript Awesome App Chrome Debugger WebSockets

  88. Live demo iPhone -> Chrome

  89. None
  90. None
  91. Heroku iPhone

  92. Streaming

  93. None
  94. UI = ƒ(data)

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