PWA Tab Synchronization

This document reviews how to synchronize data between multiple instances of a PWA running inside an Astro app. By the end of this document you will understand how to synchronize data between multiple instances of a PWA by using the NativeConnector component, Astro events and app events.


An Astro app with a tab design runs multiple instances of PWA inside the app's web views. There is no guarantee that these PWA instances will stay in sync. For example, the redux stores in the PWAs may not contain the same state. In order to synchronize the state of the PWAs App.js can be used to pass events between the instances. These events can inform the instances to update certain portions of their state.

Native Connector

NativeConnector is a hidden component in the PWA. It provides a central place where communication between the PWA and App.js can be customized.

The NativeConnector subscribes to the redux store updates using mapStateToProps and receives updates on these state changes in componentWillReceiveProps. In componentWillReceiveProps it compares the previous state values to the new state values and sends updates to App.js if state changes have occured. NativeConnector can send these updates to App.js using events or rpc calls over the JS-Native bridge. These events/rpc calls to Astro should be sent by redux actions.

The NativeConnector registers to listen for Astro events in componentDidMount and unregisters from the events in componentWillUnmount.

Broadcasting Events to Multiple Tabs

Redux state syncing is not automatic between multiple instances of the PWA running inside an Astro app. Each portion of the state that needs to be synced between instances needs to be synced manually. Functionality has been added to the Mobify PWAs to facilitate syncing.

In order to sync the state, the NativeConnector can inform App.js of the state change as described above. App.js can then broadcast this state change to all PWA instances using the PWABroadcaster. A new instance of the PWABroadcaster should be created for every web view inside App.js. The constructor for PWABroadcaster takes the web view as a parameter. It registers to listen to all events sent to the AppEvents bus and then relays any event that starts with broadcast: to its registered web view.

An event that needs to be broadcast to all tabs is first sent to the AppEvents bus. Each PWABroadcaster listens for specially named broadcast events (broadcast:) and propagates the broadcast event to the PWA. In the PWA, the NativeConnector is listening for these events and performs the actions necessary to update the state in that instance of the PWA (updates redux store and/or calls IntegrationManager).

Note: The AppEvents bus is a (backbone events)[] object inside of App.js. App.js uses AppEvents to pass internal events between its components/controllers.

// Create a new NavigationPlugin
let navigationPlugin = await NavigationPlugin.init()

// Register the NavigationPlugin to listen for broadcast events
let pwaBroadcaster = new PWABroadcaster(navigationPlugin)

// In some other part of App.js ... far, far away
// Send a broadcast event to the AppEvents bus
// Since the navigationPlugin created above has 
// registered with a PwaBroadcaster the 
// broadcast:userLoggedIn event will be sent to the 
// PWA loaded inside the navigationPlugin