Hybrid Application: Native-like Experience with WebViewâââPart 2
In the previous article, we saw how hybrid app comes with numerous benefits such as OTA (Over the air) releases, smaller app bundle size, cost-effectiveness, multi-platform support, etc.Hybrid Application: Native-like Experience with WebViewToday, letâs see how we, at Tata 1mg, have architected the hybrid app by utilizing WebViews to provide the users a seamless experience, similar to its native counterpart.
Terminology
In this article, we have used various terms that correspond to web and native apps.
- Web AppâââWeb pages we open using a browser (Chrome, Mozilla, etc.)
- Native AppâââApps that we install via the application store (Play Store, App Store) written in native languages like Swift, Java, etc.
- Hybrid AppâââPart native apps and part web apps.
- DeeplinksâââSends mobile device users directly to relevant pages in the native app rather than the web browsers.
- WebViewâââEmbeddable browser that a native application can use to display web content.
- BridgeâââLayer that permits the JavaScript code and the Native code to interact with each other.
- Event BusâââCommunication channel to send and receive data between native and web and vice-versa.
- InterfacesâââCallback methods built around Event Bus that can be invoked from both native and web app sides.
Here we have framed the article, based on the problems we encountered and the solutions we came up with while utilizing WebView for building our hybrid application.
1. Integrating WebView
Problem -How can we differentiate a normal web page from a WebView page opening in our native application?Solution -To solve this, native apps can add certain platform identification headers with the web request. With the help of this, we can identify if the client application has to serve WebView-specific behavior (like hiding header and footer, etc.) or not.
Problem -How can we navigate to and fro within WebView and Native app pages?Solution -This can be done with the help of deeplinks. They provide us the functionality to navigate between WebView and Native app pages seamlessly within a native application via implicit/explicit deeplinks.
Now we know, how to open web-based pages within the native app as WebView pages. Next, letâs see how we can create a common channel (aka. Event Bus) that bridges communication between both ends i.e. WebView to native and native to WebView.
2. Creating an Event Bus
Problem -Web pages running inside WebView are isolated from the rest of the app. So, how can we establish a communication channel between these entities?Solution -Here, WebView APIs offered by various mobile platforms (Android, iOS) can help us as they provide the functionality for communicating and interacting with both platforms (native and web) via a concept called the bridge.With the help of this bridge, the web-based JavaScript code can invoke and share data with the native app in real-time and vice-versa. Similarly, at the native end, it can listen to the events being invoked via the native bridge.
At Tata 1mg, we used the above concept, to design and develop a common Event Bus around this bridge. Using which the native apps can communicate with the WebView pages seamlessly. We also made this bus generalized, such that a single interface-based callback is compatible with both the mobile platforms we are currently supporting.But before talking about the internals, letâs discuss some of the guidelines we followed while developing the interfaces for both the native apps.
Generalizing the Interfaces
While developing the interfaces, we encountered some guidelines that need to be followed by the developers. We tried to group similar methods to a common parent, based on the action they will serve.Here are a couple of examples -
- navigationâââThis parent wrapper can take care of methods related to WebView-based navigations like closing the WebView page, toggling the navigation bar, etc.
- analyticsâââThis parent wrapper can take care of all the methods that are related to analytics.
- clipboardâââThis parent wrapper can take care of clipboard actions like cut, copy, paste, etc.
So, by defining a common parent wrapper, we have constructed the interface method as -<parent_wrapper_name><separator><interface_method>(data)E.g.ââânavigation.closeWebView(params), clipboard.copy(text) etc.Here, we have separated the parent and interface method with a dot (.) separator, similarly, we can use any other techniques like camelCase, and PascalCase as a separator.Now, letâs talk about the internals of generic interface methods (dataLayer) we have designed for data passing and invocation.
a. WebView to Native Communication (postMessage)
WebView to native app communication can be explained as calling the interface methods which are defined in the native environment, from the WebView pages. Using the same Event Bus concept, we can call these methods whenever required from our client application. We have coined these calls as postMessage-based callbacks.
These callbacks lie under the dataLayer parent wrapper, which handles calling and passing relevant data for various interface methods defined at the native end.
Updating cart details at the native end, getting microphone permissions to perform search operations on WebView pages, etc. are a couple of use cases where postMessage-based callbacks may come in handy.
b. Native to WebView Communication (onMessage)
The native to WebView communication can be achieved by exposing the web-based methods to the native environment using the same Event Bus which exists between them. As soon as the methods are available in the event bus, the native app can invoke these methods, whenever required. We have coined these calls as onMessage-based callbacks.
These callbacks also lie under the dataLayer parent wrapper, which handles calling and passing relevant data for various interface methods, defined at the web end.
Getting user-related info within WebView from the native, fetching updated location data from the native side, etc. are a couple of use cases where onMessage-based callbacks may come in handy.Now, letâs discuss some of the performance benefits we were able to achieve by utilizing WebViews.
3. Shredding 3rd Party Analytics Scripts
Problem -How can we leverage this Event Bus for navigating analytics-based events to the native platform directly?Solution -As Event Bus provides the capability to pass data between both apps, we can use this functionality to pass analytics-based information from the web to the native side using the postMessage-based callback interfaces. After the data is received at the native end, the native analytics SDKs can further pass on this data to the relevant analytics services.
This gives us some space to conditionally shred the analytics-based scripts for the WebView pages, which helps in reducing network bandwidth consumed and essentially lowers the time to interact (TTI) for the user on the web page.Next, letâs see how we have made the loaders smart enough, which gives the users a native-like feel when navigating from native to WebView pages and further on.
4. Implementing Smart Loader
Problem -While navigating from a native page to a WebView page, the load time is significant. How can we improve the user experience?Solution -Generally, whenever there is navigation from the native app to the WebView page, it takes some time to fetch the required documents and assets for the web page to open. To show this loading behavior, we used to show the native loading screen till the WebView page is fetched and becomes interactive, as a result blocking the user from interacting with the page.To solve this, we used the concept of postMessage-based callbacks to remove the native side loader whenever the first byte of the web page document reaches the native side. As a result, the user interaction with the page became much much faster.
Furthermore, we used shimmering-based loading screens, giving the users a native-like feel whenever they navigate from a native screen to a WebView-based screen. Letâs talk about it in detail.
Perceived Performance: Shimmer effect + Transitions
To reduce the load-time frustration, we used CSS-based animated skeletons, which act as a placeholder until the contents get loaded, or to visualize content that doesnât exist yet.
Additionally, we used Framer Motion to animate our page transitions and make them smoother. Animating page transitions provide an app-like experience in WebView. We used spring-based transitions supported by framer motion to create a smooth page-to-page transition on WebView pages.
5. Loading WebView smartly via Object-based loading
Problem -Can caching the assets improve the load time for the WebView page?Solution -WebViews use their mechanism of caching which usually doesnât work when we load the page for the first time which as a result takes a lot of time initially. Along with loading the HTML data, it is used to cache its resources so that if the same page opens up again, the same resources donât need to be downloaded again and the page can load faster. This works fine, but it has some issues which we wanted to optimize.Approaches:
- Using local caching through the file systemâââThis involves downloading the HTML file locally and then listening to a custom domain for caching the images which can again be used.As this involves the downloading of HTML before and then changing the domain, this doesnât help in optimizing the load time.
- Invoke the WebView activity as SingletonâââThis approach seems much more promising than the local caching. We can create the singleton for serving the same WebView object, so that cold load time can be optimized. But this would hamper displaying multiple WebViews as this would need reloading.
- Object pool patternâââThis involves keeping an object pool of WebViews which are removed once they are assigned to any view. This also enhances the load-up time of WebView.
Final Words
WebView pageâs performance can be as good as your web pageâs performance.
Over the past few years, we have invested significantly in improving our web performance, which as a result, has helped us in reducing the load time and enhancing the web experience for our end-users.Overall, the capabilities of WebView have proved to us, that it can be a great choice for anyone going with hybrid app development.I hope you enjoyed this blog!I want to thank Ayush Srivastava, Utkarsh Srivastava, Parth Mahajan, and Manav Prakash for their valuable input.
Do share your feedback and suggestions in the comments section below. Also, feel free to reach out to me on LinkedIn and Twitter.
If you liked this blog, please hit the đ .
Hybrid Application: Native-like Experience with WebViewâââPart 2 was originally published in Tata 1mg Engineering on Medium, where people are continuing the conversation by highlighting and responding to this story.
- Log in to post comments
- 1 view