Skip to content

Instantly share code, notes, and snippets.

@kiok46
Last active February 16, 2022 08:15
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kiok46/28743cd78fdd864322c12306eef0cff2 to your computer and use it in GitHub Desktop.
Save kiok46/28743cd78fdd864322c12306eef0cff2 to your computer and use it in GitHub Desktop.
Bridge React-Native and JS

Content of the Gist is from a talk by Peggy Rayzis at Chain React 2017: Chain React 2017: Breaking Down Bridging in React Native by Peggy Rayzis


In order for a native code to talk to JS you would need a bridge.

  • You need to integrate a third-party SDK.
  • High perfomance is crutial
  • You are building a brownfiel app
  • You need access to a platform to a platform API. (Camera, Gyroscope etc.), You will need to use a opensource library or create a bridge.

Threading structure in React-Native.


         NATIVE                       |                JS
                                      |
                                    BRIDGE
MAIN THREAD (Responsible for UI)      |            JS THREAD
                                    BRIDGE
SHADOW QUEUE (Layout calculations)    |  
                                    BRIDGE
NATIVE MODULES (Each native module    |
has it's own thread, while in case of |
Android they share a thread pool.)    |

Javascript thread knows about all of your the native modules at run-time, they are injected into the javascript context as a global variable.

How it looks like:

{
  moduleName: 'ExampleModule',
  constants: {},
  methods: ['ChainReact', 'bridgingIsAwesome'],
  promiseMethods: [0],
  syncMethods: [1],
}

ALL COMMUNICATION PASSES THROUGH THE BRIDGE

See 1st comment

All the messages are handled by something called as a messaage queue which has a native part and a Javascript part.

   INTERACTION HAPPENS
         |
       NATIVE
       
       MAIN THREAD -->  BRIDGE   -> JS THREAD
            |           |  ^  |
      SHADOW QUEUE <-----  |  |
                           |  |
      NATIVE MODULES <-----   ------> MESSAGE QUEUE
                                       (NATIVE & JS )

If everything is passed through this message queue to the javascript side, we need to make sure that the javascript thread is not blocked and that the message queue isn't congested(crowded).

MESSAGE QUEUE CONGESTION WILL SLOW DOWN YOUR REACT NATIVE APP.

If it is congested and the Javascript thread is blocked then we enter some weird situations. for example: We can scroll through the UI because it's done natively but javascript doesn't register our touch events. or other perfomance issues.

HOW TO PREVENT MESSAGE QUEUE CONGESTION

  • Limit passes over the bridge. (Use Native Derive for Animations), first you sent the native configurations the first time so that you won't have to keep passing information across the bridge.
  • Keep your data flat. (Try to avoid nested objects and arrays because you are just going to have conversion methods to use the data and native.)
  • Keep data light weight. (don't try to send a image as base 64 strings over the message queue that's really going to slow the application down.)
  • Write business logic in either native or JS.
  • Debug with profiling tools & logging.

INSPECTING THE REACT NATIVE MESSAGE QUEUE

type BridgeData = {
   type: number,
   module: ?string,
   method: string | number,
   args: any
}

Every message passed over te bridge has this signature, whether it's a netword request or creating a View has this exact type signature.

type: number,

maps whether you are communicating from native to Javascript or Javascript to Native.

Tool that helps to see the messages we want to see is RN Snoopy.

HOW TO BRIDGE NATIVE MODULES & UI COMPONENTS

   iOS            Android        Windows

Objective-C        Java             C#
 Swift            Kotlin

NATIVE MODULE VS. UI COMPONENT

  • Most of the time, you're choosing one or the other MAIN THREAD
  • Occasionally, you'll need to integrate both (e.g video player) SHADOW THREAD
  • Integrating both is complicated because of how threading works NATIVE MODUES in RN

First you need to choose whether you need to build a native module or a UI component A native module does not render any UI it just exports methods and constants.

BRIDGING UI COMPONENTS

VIEW MANAGER IS A FACTORY FOR VIEWS

   NATIVE                                            JS
   
--------------                                   -----------
              |                                 |           |
              |   Reference Stored on Bridge    |           |
              | ---------------------------->   |           |
              |                                 |           |
VIEW MANAGER  |   Require native component      |   REACT   |
              |                                 |           |
               <----------------------------    |           | 
              |                                 |           |
--------------                                   -----------

Whether you are building for iOS or Android you are gonig to construct a ViewManager. ViewManager orchestrates(Arrange/score) the interaction between Javascript and the View, it's a factory that creates your View and only onw instatce of the view manager is created per bridge.

The brodge knows about all the native modules(Read Above) at runtime, the view manager is like a special kind of native module except it returns UI and runs on the shadow queue. The bridge has a reference to it and it has information about the component name and any constants if you are exporting them.

If we want to construct a View we call the Require Native Component and that's what tells the view manager to create the View, it also checks the components interface via prop types to make sure that we are not passing in any incorrect types to our component.

   NATIVE                                            JS
   
--------------                                   -----------
              |                                 |           |
              |   Reference Stored on Bridge    |           |
              | ---------------------------->   |           |
              |                                 |           |
VIEW MANAGER  |   Require native component      |   REACT   |
              |                                 |           |
               <----------------------------    |           | 
              |                                 |           |
              |   Sends Reference to View       |           |
              | ---------------------------->   |           |
              |                                 |           |
--------------                                   -----------
      |
      |
     VIEW

Now, the View Manager creates the View it also stores the reference to the view instance on the bridge so we can use it on the javascript side and finally in order to display the UI we render our native View and just use it normally as we would any other react component.

   NATIVE                                            JS
   
--------------                                   -----------
              |                                 |           |
              |   Reference Stored on Bridge    |           |
              |  --------------------------->   |           |
              |                                 |           |
VIEW MANAGER  |   Require native component      |   REACT   |
              |                                 |           |
              |  <--------------------------    |           | 
              |                                 |           |
              |   Sends Reference to View       |           |
              |  --------------------------->   |           |
              |                                 |           |
--------------                                   -----------
       |                                             |
       |                 RENDER                      |
     VIEW  <----------------------------------   COMPONENT

RECAP: UI COMPONENTS

  • Only one instance of ViewManager is created per bridge, the ViewManager is a factory that cretes a View.
  • ViewManager: Declare constants, set props, event handlers and create the view.
  • When handeling events the ViewManager acts as a Delegate for all it's view instances when handeling events.
  • View: Hook up lifecycle events & render children (subviews)

NATIVE MODULES (CROSS-PLATFORM CONCEPTS)

A native component is a special type of module that returns UI. (All native modules are global variables at runtime and represented by JSON [mentioned earlier])

   NATIVE                                            JS
   
--------------                                   -----------
              |                                 |           |
              |   Reference Stored on Bridge    |           |
              |  --------------------------->   |           |
              |                                 |           |
VIEW MANAGER  |    Invoke Method on Module      |   REACT   |
              |                                 |           |
              |  <--------------------------    |           | 
              |                                 |           |
              |     Sends data Back Via         |           |
              |         Callback Or EE          |           |
              |  --------------------------->   |           |
              |                                 |           |
--------------                                   -----------

The native side is what calls the method directly and if there is any information to pass back to javascript the method can do so either by a callback, a promise or sending an event through an event emitter.

RECAP: NATIVE MODULES

  • Only one instance of the module is created per bridge, now this instance is initialized at run-time and if to communicate with JS.
  • N-->JS: Callbacks, promises or emitting event.
  • JS-->N: Method calls (call methods on the native modules and pass in any arguments which then transfers that message to the message queue.)
  • Accessing constants is synchronous (Since javascript already knows abou the module constants at runtime accessing then is synchronous and you won't have to go through the normal bridging process.)

BRIDGING PAIN POINTS

  • Context switching between languages & files.
  • So. Much Boilerplate. (You have to remember to subclass from certain RCT View managers or in the case of Android you have to override certain methods and it's kind on cinfusing to get all this boilerplate straight).
  • Instructions are piecemeal.

react-native-create-bridge CLI

https://github.com/peggyrayzis/react-native-create-bridge

cool!

@kiok46
Copy link
Author

kiok46 commented Jul 21, 2017

screen shot 2017-07-21 at 8 56 51 am

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment