Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Getting Cozy With WebViews, Part 2

DZone 's Guide to

Getting Cozy With WebViews, Part 2

We finish up this two part series by looking at why WebViews can be great for creating native-like applications.

· Web Dev Zone ·
Free Resource

Welcome back! If you missed Part 1, you can check it out here

Ideal Apps for WebViews

WebViews are not perfect for all app types. If you are building the Facebook app with 18000 classes even native might not be good enough. But there is a huge class of applications where web-based views are the best choice. If your app fits into these categories, definitely go for WebViews:

  • The app needs a network - Interactions over the internet are the biggest strength of the web. Nothing is more optimized and can provide a more robust set of network communication tools and APIs than a WebView.
  • There is no extensive need for cutting edge native APIs - If your app needs AR Kit or CoreML, then a WebView might not be the best choice. You might be able to place the general browsing and settings pages in the WebView, but if you have a native renderer, putting it in a WebView may not be worth the effort. One or two views being native is all right, as WebViews will save you a tremendous amount of effort in debugging the interactions outside of those views.
  • Everything can be built in the website - If your website is fully featured, you can build a web-based app with all the features and it can be made awesome by fine-tuning the app for the devices that it targets.
  • The app is UI/Data-based rather than CPU-based - If your app is not the one that needs to convert an iPhone into a room heater, the performance overhead of an interpreted language might be worth it. It makes UI development and experimentation with interactions and user interfaces easier. The web provides the best interaction.

Tuning WebViews for Native-Like Performance

Downloading a resource from the internet can be a huge bottleneck and every other consideration for performance take second fiddle. This changes in the world of WebViews where most of the HTML is bundled and there are very different things we need to cater to. Here are some things to consider to get native-like performance in WebViews:

  • Target a single user - WebView-based apps, unlike websites, target the same user, who logs in for the lifetime of the application. The cookies are not deleted. The requests are not blocked and multi-user considerations are simply not present. There are no cross-site security issues. Therefore, the key to great performance is caching. There is simply no need to download anything again. Stashing everything in the IndexDB is the right idea. Just like native apps, the focus should be on offline user experience and the server updates should be done whenever the network is available and in the background. Progressive Web Apps with service workers can be used if you need remote update capabilities. But starting with that may not be a great idea. Start with some bundled HTML to figure out what needs to be done to make the app perfect. Service workers should come later. Most apps update through the app store.
  • Take note of the parse times - Web apps are optimized to minimize the package size. This is not the most important thing in a native app. The source code is on the disk. Therefore there is no point in bundling JavaScript into a single file, especially if it forces the browser to parse code that it does not need to execute. JS bloat is the only reason WebView apps appear slow. But it does not have to be that way. Having 1000 files optimally split is not even a problem on the web anymore. Most users are on HTTP/2. But on native, bundling them in a huge JS file will ruin everything. In a native app written in a different language, no CPU cycles are wasted on views that need not be shown. This should be the case with the web. B use prefetch, preload, and prerender tags in a WebView app, we are not wasting bandwidth just opportunistically parsing some images, CSS, and JS files. The costs on the battery are very low and the experience benefits immense.
  • Identify the strengths - There are no browser plugins in a WebView. No JavaScript disabled mode. No worries about the web font not loading. All the extra effort needed to support these use cases and testing scenarios is not required. Instead, all the focus should be on the performance. Cache the rendered HTML on disk to prevent having to generate it again. Have a good state management library.
  • Use the right tools - HTML rendering is highly optimized and the browser takes extreme care not to waste cycles rendering stuff that is not needed. But still, the DOM is extremely expensive. To get native-like performance, we need to take some cues from native code. Picking a virtual scroll library is essential if we need a scroll list. Animations in JavaScript, until web animations become available, is not a great idea. Images should be optimized to the view they will show up in. The need for the browser to relayout should be prevented with things like size attributes in images and preloading of the content.
  • Do not go overboard - While many native app teams are happy going with a simpler design, as soon as the web technology is brought into the picture more customizations are needed. Not many apps ship with custom fonts but almost all WebView-based apps are forced to adopt one. Similarly, developers want to share code as much as possible. These goals deter the focus from quality. As long as the web-based apps target the lowest common denominator, they will remain far behind native code. The WebView app should not be sharing code with the website to begin with. First, get the best app out and then focus on sharing. The app can act as a forerunner to the website meant to replace it when the lowest browser supports everything it needs. There will still be avenues to share code. And even if there is none shared, there was nothing shared in the native world as well so we are not worse off.
  • Realize the limitations - Some screens are not ideal to be WebViews. For example, if your application’s core is something that depends on real-time updates from the photo gallery, phonebook, or camera, you can hook up Cordova or pass messages but it might be better to just use native code for those views. This does not mean the app cannot be a WebView app. The photo view or the phonebook view can be a native view that calls back to the core WebView when done. That way the core logic can still reside in the WebView and be cross-platform while the platform specific performance sensitive pieces could reside in native code.
  • Use the right defaults - Almost all apps are on retina display devices, with a wide gamut of support by default almost everywhere. If building WebView-based apps starts to support the highest device feature set, adding backward compatibility is easy (especially with Babel and PostCSS) and we never know if we will support the older device by the time we get to a release. Optimize for a feature that’s new in a new device. Users paid handsomely for the new handset and they expect the apps to look much better on the new device. Developers need to respect those wishes with the WebViews, just like they do with native code.

Raw WebViews vs. Cordova vs. React Native 

Raw WebViews are good for most workflows, especially if there is a team of native app developers who are building the hybrid part of the application. They allow native developers to feel at home while the web developers can fully implement most of the cross-platform logic. The boilerplate has been reduced over time and with most requirements never actually needing native code, the reasons for not putting it in a WebView are diminishing at a great speed.

Cordova makes it faster but it comes with a lot of baggage that is not relevant in the modern world. Cordova is like jQuery, it makes the job easier, works around platform-specific bugs, and significantly speeds up the process to get something up and running. But in the modern OSs, it is not essential. If we are new to the platform we can use it to get started. But most of its functionality is natively available. At some point you can replace your entire framework dependency with a ployfill that is implemented over a WebView. Cordova is perfect if you do not want to maintain a build system as a PhoneGap build can save you the cost of buying a Mac.

React Native is an interesting experiment. It started with the concept of using Native Controls directed by JavaScript, but, over time, with things like React Navigation, the community has gravitated away from using true native controls to custom views. There are two big advantages to React Native: out of the box platform specific UI and the ability to write a custom native control surrounded by regular controls. Its API surface is very small in comparison to the web platform and new features like CSS Grids may never end up in the platform. WebViews also have native controls, although things like switches have not yet been implemented. React Native is a good idea if you are okay with the limitations delineated above and need a custom control so tightly integrated with JavaScript views that WebViews are prohibitive. Otherwise, WebViews with React would be easier to develop over and give a comparable performance for most use cases.

Conclusion

Web applications are getting as powerful as native desktop applications and the difference will soon be indistinguishable. We still need to write assembly-level code for really low-level, extremely performance sensitive stuff but even those strong proponents of their real native skills never go down to assembly. We are entering the golden age of developing mobile apps using web technologies. Web technologies are the present of application development. WebViews are a great way to make them go native.

Topics:
web dev ,webviews ,native application development ,web application development

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}