This is part 2 of a 3 part series
React has become more popular, as well as more mature, over the last four years since its release by Facebook. It has become one of the go-to technologies for people looking to componentize the front-end of any web application. It also helps that an entire mobile stack is built around React in the form of ReactNative. The components are wonderful, however there can be a burdensome learning curve. But, in the end, there’s the payoff of highly reusable code and a better user experience.
To help people infuse React apps with image and video management services, Cloudinary provides a fully formed set of React components that can quickly be configured and dropped into your application. Your app is already equipped with management and manipulation of media assets and delivering them via a CDN, and you already have a React app delivering the content to your end user. Now, you may want to boost performance and make your end user’s experience even better. To do that you’ll want to follow the tenets of React Progressive Web Apps.
What are Progressive Web Apps? There are many sources where you can learn more, including an article we recently wrote about why you should care. But how do you introduce that into an already complex stack of a React application? We’ll show you, step-by-step.
You’ve got your app and it’s using the Cloudinary React components. It may look a little like https://github.com/ukmadlz/cloudinary-pwa-react/releases/tag/basic-media-app. So what steps do you need to take to make it a React Progressive Web App?
Is your application secure? All the features needed to turn your application into a Progressive Web App can only be used from a connection being served over HTTPS. If you are not doing so already, you can find guides for using services like CloudFlare to quickly implement an HTTPS cache in front of your application. When developing, localhost and 127.0.0.1 are considered to be secure and trusted endpoints, so you can develop without using certificates locally.
Is your application discoverable? Part of making a web app a Progressive Web App is introducing a web manifest. This JSON file describes the application, as well as assets, to make it easier to use on different devices. For the sake of Progressive Web Apps on Android, it helps with the app name, description, splash page, Chrome shell wrapper, and home screen icon.
The most basic web manifest looks like this:
It informs the browser of the preferred icon, similar to how the favicon works, and gives the name and brief description of the app itself. This information is used differently by each browser, from helping the internal history search to providing richer information for the “recently visited” pieces. But it is all designed to make the application easier to discover, or, in most cases, re-discover quickly. A more advanced file, like the one we use in our demo app, goes a step further and helps the browser interpret the app.
This file describes the basics for the app to become discoverable, as well as the metadata to make it easier for the browser to display the content and make it behave correctly as a near-native app. To make this manifest visible to the browser, you need to add the following tags to the
<head> of your page:
These meta tags tell the browser (1) where to find the manifest, (2) the setup of the display and (3) the app’s theme color. It does this to make it discoverable and display correctly on mobile devices.
Does the app work offline? The next most important part of the app is to make sure it works offline (otherwise, by definition, it’s not a Progressive Web App). The way to do this is to register a service worker that will run in the background and process information from the cache, as well as from the internet when it has a network connection. Since not all popular browsers are compliant with the service worker specification, a bit of feature detection is necessary.
This code snippet checks that the service worker is part of the navigator object, and only if it’s available does it attempt to register a new one located at
sw.js and gives it a scope relative to
./. If successful, it creates a new instance of
sw.js and will execute the event code in the service worker. The complete service worker we use in this app can be found here. The file is being triggered by three key events:
- Install Event: Generating a cache when the service worker is first registered, then proceeding to save all URLs that we want saved from the start.
- Activate Event: Running when the service worker is recalled by the browser, e.g. when a new browser session is started. It performs general clean up to stop the cache from growing too large and deletes any caches that are no longer registered for use.
- Fetch Event: Caching things on the fly is done whenever the browser makes any request. It fires the fetch event that we can intercept in the service worker. Here we can check against the cache for the item, and either serve a cached copy or fetch it. In the latter case, we cache the fetched item and serve it to the end-user.
The events above guarantee that the end users have everything they need in the browser, so they can continue to get use out of a web app when offline. This is essential for improving performance and user experience in areas of degraded signal when accessing the app over a bad mobile connection.